|CA gymnastics, an account of some testing|
In order to be prepared for future requests on the NIKHEF/DutchGrid CA, I did some `CA gymnastics'. Topics of interest were:
An invaluable resource was the CA manual published by the German research networking centre DFN as DFN bericht nr. 89: Aufbau und Betrieb einer Zertifizierungsinstanz.
|Singing a cert with the CA key with arbitrary serial|
This command emulates the entire functionality of the compound openssl ca command. Provided we have a "ca.cnf" file that contains a proper series of extensions for the user cert, we can do:
TAG=20010531-170422 EMAILemail@example.com CAROOT=. echo "intended_cert_serial_no" > newserial openssl x509 \ -req \ -days 9663 \ -extfile ca.cnf -extensions ext_user \ -CA data/cacert.pem -CAkey data/private/cakey.pem \ -CAserial newserial \ -in original_request.pem \ -out newercert.pem
|Adding attributes to an existing CA key|
If you have an existing CA cert that already signed some user certs but you need to modify or add extenstions (or change the validity of the CA cert), you can reuse the old key pair. In this case, the issued user certs remain valid when checked against the new CA cert. Note that you should never change the DN (you cant anyways) and you should can keep the same serial in this case (at least as long as your users will accept such a change!). Exactly this change may be forthcoming for the Globus CA cert starting with the new release in the summer of 2001. The new GlobusCA cert is already in CVS (see the Globus java mailing list, message 00067).
First, update the ca.cnf file to include the new extensions. Note that you will have to repeat all extensions you want! By converting the CA cert to a request.pem file, you loose all current extensions! We will use the -days argument to extend the CA certs life time.
The last command will generate a self-signed cert with the default serial number 0 and a life time of 5 years. If we now verify an existing cert signed by this ca, if should verify OK:vi ca.cnf mv data/cacert.pem data/original-cacert.pem openssl x509 \ -x509toreq \ -in data/original-cacert.pem \ -signkey data/private/cakey.pem \ -out carequest.pem TAG="" EMAIL="" openssl x509 \ -req \ -days 1826 \ -extfile ca.cnf -extensions ext_ca \ -signkey data/private/cakey.pem \ -in carequest.pem \ -out data/cacert.pem
openssl verify -CAfile data/cacert.pem data/newcerts/01.pem
|Adding attributes to an existing user cert|
If you only have an existing cert you're out of luck. You will need the original certificate request and the CA private key. Then, make (or midify) a configuration file with the full required set of extensions. In this example, the ca.cnf file has a section ext_user that also requires two environment variables set (EMAIL and TAG).
The default version of the OpenSSL "ca" tool does not allow renewal of a certificate while the old one is still valid. In order to counter this side effect, we have to forcibly expire the cert. We should not revoke it, since in that case the old cert will be refused by complying relying parties, where we want a smooth transition period. Therefore, look for the DN in the index.txt file for the user's DN and put the marker (first character on the line) to "E". You can subsequently sign the request again with a new expiry date.
Note that a new serial number will be assigned to this cert (this is the proper thing to do, since there might be a need to revoke the old as well as the new cert during the transition period!). You can also modify the X.509v3 extensions as this point.
|Certificate chaining, re-signing self-signed certs and cross-certification|
If you want to cross-certify an existing CA, you will need that CA's public certificate and your own CA's private key. Use the following command:
Note well: you need to use X.509v3 extensions that are appropriate for CA's (i.e., "basicConstraints = critical, CA:true")!EMAIL="firstname.lastname@example.org" \ TAG="crosscert X-20010601-113522" \ openssl ca \ -config ca.cnf \ -policy policy_anything \ -preserveDN \ -extensions ext_ca \ -ss_cert cacert-nikhef-ms.pem \ -out crosscertified_cert.pem
Creating subordinate CA's is somewhat different. First, we drastically extend
our ca.cnf file, now called subord.cnf. This
config file has two ca's, called "niktest1" and "subord". You can
select one of them on the commandline of the openssl ca using
the -name argument.
After updating the subord.cnf file, we recreate the usual directory structure (see the ca.sh script for details) and generate a request (so not a self-signed X.509 cert as is usual for a ca cert!):
Now, we sign the request with the "niktest1" CA:openssl req \ -new \ -config subord.cnf \ -keyout subord/private/cakey.pem \ -out subord/careq.pem
Now the new cacert.pem can successfully be used as a CA. For verification, you'll need both the subord CA cert and the root CA cert (niktest1). But first, generate a request from a test user like this:openssl ca \ -config subord.cnf -name niktest1 \ -policy policy_anything -preserveDN \ -extensions ext_subord_ca \ -days 1095 \ -in subord/careq.pem \ -out subord/cacert.pem
and sign it:openssl req \ -new \ -config subord.cnf \ -keyout testuser/key.pem \ -out testuser/req.pem
EMAIL="email@example.com" \ TAG="subord-20010601-111623" \ openssl ca \ -config subord.cnf -name subord \ -preserveDN \ -extensions ext_user \ -in testuser/req.pem \ -out testuser/cert.pem
will return OK. IF we remove the niktest1 CA cert from this direcory, it will fail, just like the equivalent command:openssl verify -CApath ./dir testuser/cert.pem
telling you:openssl verify -CAfile subord/cacert.pem testuser/cert.pem
testuser/cert.pem: /C=NL/O=NIKHEF/CN=Subordinate CA below niktest1 error 2 at 1 depth lookup:unable to get issuer certificate
As a reference and maybe as a guideline for extensions in certs, I collected some different certs from the 'Net: