Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

In 2004, I set up a small certification authority using OpenSSL on Linux and the simple management scripts provided with OpenVPN. In accordance with the guides I found at the time, I set the validity period for the root CA certificate to 10 years. Since then, I have signed many certificates for OpenVPN tunnels, web sites and e-mail servers, all of which also have a validity period of 10 years (this may have been wrong, but I didn't know better at the time).

I have found many guides about setting up a CA, but only very little information about its management, and in particular, about what has to be done when the root CA certificate expires, which will happen some time in 2014. So I have the following questions:

  • Will the certificates that have a validity period extending after the expiry of the root CA certificate become invalid as soon as the latter expires, or will they continue to be valid (because they were signed during the validity period of the CA certificate)?
  • What operations are needed to renew the root CA certificate and ensure a smooth transition over its expiry?
    • Can I somehow re-sign the current root CA certificate with a different validity period, and upload the newly-signed cert to clients so that client certificates remain valid?
    • Or do I need to replace all client certificates with new ones signed by a new root CA certificate?
  • When should the root CA certificate be renewed? Close to expiry, or a reasonable time before expiry?
  • If the renewal of the root CA certificate becomes a major piece of work, what can I do better now to ensure a smoother transition at the next renewal (short of setting the validity period to 100 years, of course)?

The situation is made slightly more complicated by the fact that my only access to some of the clients is through an OpenVPN tunnel that uses a certificate signed by the current CA certificate, so if I have to replace all client certs, I will need to copy the new files to the client, restart the tunnel, cross my fingers and hope that it comes up afterwards.

share|improve this question
add comment

4 Answers

up vote 39 down vote accepted
+100

Keeping the same private key on your root CA allows for all certificates to continue to validate successfully against the new root; all that's required of you is to trust the new root.

The certificate signing relationship is based on a signature from the private key; keeping the same private key (and, implicitly, the same public key) while generating a new public certificate, with a new validity period and any other new attributes changed as needed, keeps the trust relationship in place. CRLs, too, can continue over from the old cert to the new, as they are, like certificates, signed by the private key.


So, let's verify!

Make a root CA:

openssl req -new -x509 -keyout root.key -out origroot.pem -days 3650 -nodes

Generate a child certificate from it:

openssl genrsa -out cert.key 1024
openssl req -new -key cert.key -out cert.csr

Sign the child cert:

openssl x509 -req -in cert.csr -CA origroot.pem -CAkey root.key -set_serial 01 -out cert.pem
rm cert.csr

All set there, normal certificate relationship. Let's verify the trust:

# openssl verify -CAfile origroot.pem -verbose cert.pem
cert.pem: OK

Ok, so, now let's say 10 years passed. Let's generate a new public certificate from the same root private key.

openssl req -new -key root.key -out newcsr.csr
openssl x509 -req -days 3650 -in newcsr.csr -signkey root.key -out newroot.pem
rm newcsr.csr

And.. did it work?

# openssl verify -CAfile newroot.pem -verbose cert.pem
cert.pem: OK

But.. why? They're different files, right?

# sha1sum newroot.pem
62577e00309e5eacf210d0538cd79c3cdc834020  newroot.pem
# sha1sum origroot.pem
c1d65a6cdfa6fc0e0a800be5edd3ab3b603e1899  origroot.pem

Yes, but, that doesn't mean that the new public key doesn't cryptographically match the signature on the certificate. Different serial numbers, same modulus:

# openssl x509 -noout -text -in origroot.pem
        Serial Number:
            c0:67:16:c0:8a:6b:59:1d
...
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:bd:56:b5:26:06:c1:f6:4c:f4:7c:14:2c:0d:dd:
                    3c:eb:8f:0a:c0:9d:d8:b4:8c:b5:d9:c7:87:4e:25:
                    8f:7c:92:4d:8f:b3:cc:e9:56:8d:db:f7:fd:d3:57:
                    1f:17:13:25:e7:3f:79:68:9f:b5:20:c9:ef:2f:3d:
                    4b:8d:23:fe:52:98:15:53:3a:91:e1:14:05:a7:7a:
                    9b:20:a9:b2:98:6e:67:36:04:dd:a6:cb:6c:3e:23:
                    6b:73:5b:f1:dd:9e:70:2b:f7:6e:bd:dc:d1:39:98:
                    1f:84:2a:ca:6c:ad:99:8a:fa:05:41:68:f8:e4:10:
                    d7:a3:66:0a:45:bd:0e:cd:9d
# openssl x509 -noout -text -in newroot.pem
        Serial Number:
            9a:a4:7b:e9:2b:0e:2c:32
...
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:bd:56:b5:26:06:c1:f6:4c:f4:7c:14:2c:0d:dd:
                    3c:eb:8f:0a:c0:9d:d8:b4:8c:b5:d9:c7:87:4e:25:
                    8f:7c:92:4d:8f:b3:cc:e9:56:8d:db:f7:fd:d3:57:
                    1f:17:13:25:e7:3f:79:68:9f:b5:20:c9:ef:2f:3d:
                    4b:8d:23:fe:52:98:15:53:3a:91:e1:14:05:a7:7a:
                    9b:20:a9:b2:98:6e:67:36:04:dd:a6:cb:6c:3e:23:
                    6b:73:5b:f1:dd:9e:70:2b:f7:6e:bd:dc:d1:39:98:
                    1f:84:2a:ca:6c:ad:99:8a:fa:05:41:68:f8:e4:10:
                    d7:a3:66:0a:45:bd:0e:cd:9d

Let's go a little further to verify that it's working in real world certificate validation.

Fire up an Apache instance, and let's give it a go (debian file structure, adjust as needed):

# cp cert.pem /etc/ssl/certs/
# cp origroot.pem /etc/ssl/certs/
# cp newroot.pem /etc/ssl/certs/
# cp cert.key /etc/ssl/private/

We'll set these directives on a VirtualHost listening on 443 - remember, the newroot.pem root certificate didn't even exist when cert.pem was generated and signed.

SSLEngine on
SSLCertificateFile /etc/ssl/certs/cert.pem
SSLCertificateKeyFile /etc/ssl/private/cert.key
SSLCertificateChainFile /etc/ssl/certs/newroot.pem

Let's check out how openssl sees it:

# openssl s_client -showcerts -CAfile newroot.pem -connect localhost:443

Certificate chain
 0 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=server.lan
   i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
 1 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
   i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
-----BEGIN CERTIFICATE-----
MIICHzCCAYgCCQCapHvpKw4sMjANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJB
...
-----END CERTIFICATE-----
(this should match the actual contents of newroot.pem)
...
Verify return code: 0 (ok)

Ok, and how about a browser using MS's crypto API? Gotta trust the root, first, then it's all good, with the new root's serial number:

newroot

And, we should still be working with the old root, too. Switch Apache's config around:

SSLEngine on
SSLCertificateFile /etc/ssl/certs/cert.pem
SSLCertificateKeyFile /etc/ssl/private/cert.key
SSLCertificateChainFile /etc/ssl/certs/origroot.pem

Do a full restart on Apache, a reload won't switch the certs properly.

# openssl s_client -showcerts -CAfile origroot.pem -connect localhost:443

Certificate chain
 0 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=server.lan
   i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
 1 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
   i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
-----BEGIN CERTIFICATE-----
MIIC3jCCAkegAwIBAgIJAMBnFsCKa1kdMA0GCSqGSIb3DQEBBQUAMFQxCzAJBgNV
...
-----END CERTIFICATE-----
(this should match the actual contents of origroot.pem)
...
Verify return code: 0 (ok)

And, with the MS crypto API browser, Apache's presenting the old root, but the new root's still in the computer's trusted root store. It'll automatically find it and validate the cert against the trusted (new) root, despite Apache presenting a different chain (the old root). After stripping the new root from trusted roots and adding the original root cert, all is well:

oldroot


So, that's it! Keep the same private key when you renew, swap in the new trusted root, and it pretty much all just works. Good luck!

share|improve this answer
    
Awesome reply, thanks! So all hope is not lost, and I will only have to upload the new root cert to all clients for them to trust? That's even better than I thought, because OpenVPN allows multiple CA certificates in one file, so I can simply put both the old and new CA cert into a single file and the transition should be seamless. –  Remy Blank Sep 4 '11 at 20:47
    
@Remy Yup - you'll need to make sure that anything that's presenting a certificate chain starts presenting the new one before the old one expires, and you'll probably want to get the old one out of the trusted roots before it expires, but all of the certs issued against the old root should validate with no problem against the new root. –  Shane Madden Sep 5 '11 at 17:13
    
Anyways, what's the point of creating a new root certificate if you're just going to reuse the same private key? If you keep doing this over and over, then what's the point of even having an expiration date for the certificate? I thought the root expiration was used to force admins to make a newer (most likely stronger) private key that is more secure against the ever advancing machines trying to break the keys. A 40 bit key made 20 years ago is not secure enough for –  jvhashe Aug 22 '13 at 19:00
    
@jvhashe If the root certificate's no longer cryptographically strong enough, then you should be getting rid of it regardless of its expiration date. If you're generating your own root, there's nothing stopping you from setting it to expire hundreds of years past when you'll no longer be on the planet. Expiration is barely relevant on a root certificate - and for a child certificate, the expiration isn't really about cryptographic strength either (ask the CAs who are prepping to revoke all 1024-bit certs in October) - see here for more info. –  Shane Madden Aug 23 '13 at 1:19
add comment

When your root certificate expires, so do the certs you've signed with it. You will have to generate a new root cert and sign new certificates with it. If you don't want to repeat the process every few years the only real option is to extend the valid date on the root cert something like ten or twenty years: The root I generated for my own use I set out twenty years.

You can't "renew" a root cert. All you can do is generate a new one.

Generate a new root at least a year or two before your old one expires so you have time to change over without being against a time wall if something goes wrong. That way you can always temporarily switch back to the old certs until you get your teething problems with the new one resolved.

As far as the VPN tunnels go, I would set up a couple of testbed servers to experiment with so you understand precisely what you have to do before you do it with a client's machine.

share|improve this answer
    
This reply seems to suggest that it is possible to renew a root certificate, by re-using its key. But I suspect this is no different from starting from scratch, as the new cert will have a different signature, and hence won't validate existing client certs. –  Remy Blank Sep 4 '11 at 11:47
    
yes, you can extend valid period... and is less work than recreate all pki, client certificates, and retrust new root... –  ggrandes Jan 22 '13 at 16:25
add comment

Basic mode to extend the valid period of root (you need the public X.509 and asociated private key):

Generate the CSR from public X.509 and private key:

openssl x509 -x509toreq -in XXX.crt -signkey XXX.key -out XXX.csr

Re-sign the CSR with private key:

openssl x509 -in XXX.csr -out XXX.crt -signkey XXX.key -req -days 365
share|improve this answer
add comment

I've noticed that CA extensions could be missing in the renewed certificate of the original CA key. This worked more appropriately for me (it creates a ./renewedselfsignedca.conf where v3 CA extensions are defined, and ca.key and ca.crt are assumed to be the original CA key and certificate):

openssl x509 -x509toreq -in ca.crt -signkey ca.key -out renewedselfsignedca.csr
echo -e "[ v3_ca ]\nbasicConstraints= CA:TRUE\nsubjectKeyIdentifier= hash\nauthorityKeyIdentifier= keyid:always,issuer:always\n" > renewedselfsignedca.conf
openssl x509 -req -days 1095 -in renewedselfsignedca.csr -signkey ca.key -out renewedselfsignedca.crt -extfile ./renewedselfsignedca.conf -extensions v3_ca
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.