Refrescar el certificado X.509 de una entidad de certificación para OpenVPN, manteniendo sus firmas previas como válidas
Tengo un servicio OpenVPN privado desde hace diez años. Todos los certificados X.509 de acceso y el certificado X.509 del servidor OpenVPN están firmados por una autoridad de certificación privada.
El problema es que esa autoridad de certificación tiene una validez de diez años, caducando en unos meses. En ese momento OpenVPN dejará de funcionar si no hago nada.
La solución evidente es crear un nuevo certificado para la autoridad de certificación privada, con una validez de otros diez años (por ejemplo). El problema es que eso requiere emitir nuevos certificados X.509 para el servidor OpenVPN y para todos los clientes. Todo el cambio tiene que estar coordinado, porque los certificados X.509 previos dejarían de ser válidos en cuanto se active la nueva clave de la autoridad de certificación.
¿Cómo refrescar una autoridad de certificación para extender su fecha de caducidad manteniendo la validez de los certificados X.509 firmados previamente?
Los certificados X.509 tienen un número de serie y una fecha de mínima y otra máxima de validez. ¿Es posible modificar dichas fechas del certificado X.509 de la autoridad de certificación y que sigan funcionando las firmas antiguas?
Pues lo cierto que sí. A la hora de verificar una cadena de validación X.509, el RFC que define el estándar solo exige que cada certificado de la cadena firme correctamente el anterior y que cada eslabón de la cadena sea válido en el momento de la verificación. No hay relación entre las fechas de validez de cada eslabón y las fechas de las firmas que crean la cadena de certificados X.509.
El RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile, en su sección 6.1.3, dice lo siguiente:
6.1.3. Basic Certificate Processing
The basic path processing actions to be performed for certificate i (for all i in [1..n]) are listed below.
- Verify the basic certificate information. The certificate MUST satisfy each of the following:
[...]
- The certificate validity period includes the current time.
- At the current time, the certificate is not revoked. This may be determined by obtaining the appropriate CRL (Section 6.3), by status information, or by out-of-band mechanisms.
[...]
Según esto, si pudiésemos generar un nuevo certificado X.509 para la autoridad de certificación con fechas de validez actualizadas, pero manteniendo tanto el número de serie (que enlaza las firmas digitales) como la clave pública y privada (que validan las firmas digitales), tendríamos un nuevo certificado X.509 con la expiración futura deseada y no arruinaríamos los certificados X.509 previos de los clientes OpenVPN.
Bastaría con actualizar el certificado X.509 de la autoridad de certificación en el servidor y los clientes OpenVPN poco a poco, antes de que caduque el certificado X.509 original de la autoridad de certificación. Tenemos unos seis meses para completar el proceso y cada cliente puede hacerlo a su ritmo. Simplemente hay que completar el proceso antes de que caduque el certificado original.
Los valores actuales del certificado X.509 de mi autoridad de certificación OpenVPN son:
$ openssl x509 -in ca.crt -text [...] Serial Number: d2:51:6d:17:a1:d7:47:84 Signature Algorithm: sha256WithRSAEncryption [...] Validity Not Before: Jan 15 00:44:02 2015 GMT Not After : Jan 12 00:44:02 2025 GMT [...]
Para refrescar las fechas de validez del certificado X.509 de la autoridad de certificación OpenVPN hay que hacer lo siguiente:
$ openssl x509 -x509toreq -in ca.crt -signkey ca.key -out new-ca.csr Getting request Private Key Generating certificate request $ echo -e "[ v3_ca ]\nbasicConstraints= CA:TRUE\nsubjectKeyIdentifier= hash\nauthorityKeyIdentifier= keyid:always,issuer:always\n" >/tmp/ca.conf $ openssl x509 -req -days 3650 -in new-ca.csr -signkey ca.key \ -out new-ca.cert -set_serial 0xd2516d17a1d74784 \ -extfile /tmp/ca.conf -extensions v3_ca Signature ok subject=C = ES, ST = MAD, L = Madrid, O = jcea, CN = jcea CA, emailAddress = jcea@jcea.es Getting Private key $ mv new-ca.cert ca.crt $ openssl x509 -in ca.crt -text [...] Serial Number: d2:51:6d:17:a1:d7:47:84 Signature Algorithm: sha256WithRSAEncryption [...] Validity Not Before: May 21 17:49:52 2024 GMT Not After : May 19 17:49:52 2034 GMT [...]
Los comandos hacen lo siguiente:
-
Genera un CSR con la misma clave pública y privada que el certificado X.509 actual de la autoridad de certificación de mi red OpenVPN.
-
Crea un fichero de configuración ad hoc para crear un certificado X.509 que sea una autoridad de certificación y diversos ajustes relacionados.
-
Genera un certificado X.509 con una validez de diez años y con el mismo número de serie que el certificado X.509 que queremos sustituir.
-
Reemplaza el certificado X.509 original.
Aquí también reiniciaríamos el servidor OpenVPN para que actualice su certificado y comprobaríamos que los clientes OpenVPN se conectan con normalidad. Es decir, que el nuevo certificado X.509 de la autoridad de certificación verifica correctamente los certificados X.509 antiguos de los clientes OpenVPN.
-
Muestra los datos del nuevo certificado X.509, confirmando que el número de serie y las fechas de validez son los esperados.
Una vez que comprobamos que el nuevo certificado X.509 de la autoridad de certificación del servicio OpenVPN funciona correctamente, solo quedaría ir distribuyéndolo a los clientes OpenVPN a medida que vaya siendo posible y conveniente.
Sobre todo esto, algunos detalles que siempre me han parecido curiosos o que valen la pena considerar:
-
Que sea necesario utilizar el mismo número de serie es algo a investigar. En principio no debería ser necesario porque la identidad del firmante de un certificado X.509 es un hash de la clave pública, pero en mis experimentos los resultados eran inconsistentes. Puede ser que simplemente cometiese algún error. En cualquier caso, es más fácil así.
Lo que se ve en el certificado X.509 firmado es:
$ openssl x509 -in server.crt -text [...] X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Cert Type: SSL Server [...] X509v3 Subject Key Identifier: 7C:85:C8:23:3D:DB:83:A1:14:B1:5E:74:F0:7E:A2:03:9F:B3:0C:01 X509v3 Authority Key Identifier: keyid:71:B6:DC:70:09:85:9E:47:77:D9:8B:91:43:7E:0F:8D:BF:7E:7B:40 DirName:/C=ES/ST=MAD/L=Madrid/O=jcea/CN=jcea CA/emailAddress=jcea@jcea.es serial:D2:51:6D:17:A1:D7:47:84 [...]
Obsérvese que ahí aparece el número de serie de la autoridad de certificación firmante.
-
Para mantener la historia del certificado X.509 de la autoridad de certificación, se podría mantener la fecha de creación original del certificado X.509. Se pueden controlar las fechas de validez con los parámetros -startdate y -enddate a la hora de realizar la autofirma.
-
Una autoridad de certificación puede firmar un certificado X.509 cuya expiracion es posterior a la propia expiración de la autoridad de certificación.
-
Al mantener la clave pública y privada del certificado X.509 de la autoridad de certificación, es importante que sigan siendo fuertes para los estándares modernos y que no se hayan visto comprometidas. En mi caso la clave pública RSA creada en 2015 tiene 2048 bits, lo que se sigue considerando seguro en el año 2024. Nos valdrán diez años más, salvo sorpresas.
Por el mismo motivo, el algoritmo de hash debe seguir siendo resistente a ataques. En mi caso uso SHA256. Hoy se valora como seguro.
En general, toda las características criptográficas del certificado X.509 original deben seguir considerándose seguras.