Mantener la misma clave privada en su CA raíz permite que todos los certificados continúen validándose con éxito en la nueva raíz; todo lo que se requiere de ti es confiar en la nueva raíz.
La relación de firma del certificado se basa en una firma de la clave privada; mantener la misma clave privada (e, implícitamente, la misma clave pública) mientras se genera un nuevo certificado público, con un nuevo período de validez y cualquier otro atributo nuevo modificado según sea necesario, mantiene la relación de confianza en su lugar. Las CRL también pueden continuar del antiguo certificado al nuevo, ya que, como los certificados, están firmados por la clave privada.
Entonces, ¡verifiquemos!
Hacer una CA raíz:
openssl req -new -x509 -keyout root.key -out origroot.pem -days 3650 -nodes
Genere un certificado hijo a partir de él:
openssl genrsa -out cert.key 1024
openssl req -new -key cert.key -out cert.csr
Firme el certificado de niño:
openssl x509 -req -in cert.csr -CA origroot.pem -CAkey root.key -create_serial -out cert.pem
rm cert.csr
Todo listo allí, relación de certificado normal. Verifiquemos la confianza:
# openssl verify -CAfile origroot.pem -verbose cert.pem
cert.pem: OK
Ok, entonces, digamos que pasaron 10 años. Generemos un nuevo certificado público a partir de la misma clave privada raíz.
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
Y ... ¿funcionó?
# openssl verify -CAfile newroot.pem -verbose cert.pem
cert.pem: OK
¿Pero por qué? Son archivos diferentes, ¿verdad?
# sha1sum newroot.pem
62577e00309e5eacf210d0538cd79c3cdc834020 newroot.pem
# sha1sum origroot.pem
c1d65a6cdfa6fc0e0a800be5edd3ab3b603e1899 origroot.pem
Sí, pero eso no significa que la nueva clave pública no coincida criptográficamente con la firma en el certificado. Diferentes números de serie, mismo módulo:
# 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
Vayamos un poco más allá para verificar que está funcionando en la validación de certificados del mundo real.
Encienda una instancia de Apache y probémosla (estructura del archivo debian, ajuste según sea necesario):
# cp cert.pem /etc/ssl/certs/
# cp origroot.pem /etc/ssl/certs/
# cp newroot.pem /etc/ssl/certs/
# cp cert.key /etc/ssl/private/
Estableceremos estas directivas en una VirtualHost
escucha en 443: recuerde, el newroot.pem
certificado raíz ni siquiera existía cuando cert.pem
se generó y firmó.
SSLEngine on
SSLCertificateFile /etc/ssl/certs/cert.pem
SSLCertificateKeyFile /etc/ssl/private/cert.key
SSLCertificateChainFile /etc/ssl/certs/newroot.pem
Veamos cómo lo ve openssl:
# 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, ¿y qué tal un navegador que usa la API criptográfica de MS? Primero tengo que confiar en la raíz, luego todo está bien, con el número de serie de la nueva raíz:
Y, todavía deberíamos estar trabajando con la raíz antigua, también. Cambie la configuración de Apache:
SSLEngine on
SSLCertificateFile /etc/ssl/certs/cert.pem
SSLCertificateKeyFile /etc/ssl/private/cert.key
SSLCertificateChainFile /etc/ssl/certs/origroot.pem
Haga un reinicio completo en Apache, una recarga no cambiará los certificados correctamente.
# 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)
Y, con el navegador MS crypto API, Apache presenta la raíz anterior, pero la nueva raíz todavía está en el almacén raíz de confianza de la computadora. Lo encontrará automáticamente y validará el certificado contra la raíz de confianza (nueva), a pesar de que Apache presenta una cadena diferente (la raíz antigua). Después de quitar la nueva raíz de las raíces confiables y agregar el certificado raíz original, todo está bien:
¡Eso es todo! Mantenga la misma clave privada cuando renueve, cambie la nueva raíz confiable y prácticamente todo funciona . ¡Buena suerte!