Generar y convertir claves y certificados con OpenSSL

Escrito por picodotdev el , actualizado el .
programacion seguridad software software-libre web
Enlace permanente Comentarios

Usando los comandos expuestos en este artículo y con OpenSSL podemos crear una clave pública y privada para usarlo con ssh o para cifrar y descifrar mensajes, un certificado autofirmado que podremos usar en un servidor de aplicaciones para usar un protocolo seguro y también convertir las claves y certificados a uno de los formatos aceptados por la aplicación que usemos.

OpenSSL

Para un uso personal como enviar correos o archivos cifrados o firmados digitalmente usar GnuPG es una buena opción. En Internet los servidores también se aprovechan del uso de criptografía para realizar comunicaciones seguras entre el usuario y el servidor.

Para hacer uso en un servidor de una comunicación https donde los datos viajan cifrados y sin que otras partes salvo el usuario y el servidor puedan acceder a los datos necesitamos un certificado digital. Un certificado es un archivo que contiene la clave pública sirviéndonos para verificar su autenticidad. Un certificado autofirmado es un certificado firmado con la misma clave privada asociada a la clave pública que contiene el certificado. Un certificado autofirmado es suficiente para un entorno de pruebas pero en un servidor para proporcionar confianza a los usuarios deberemos solicitar que una autoridad de certificados que nos firme con su clave nuestro certificado, si el usuario confía en esa autoridad de certificado puede de esta manera confiar en nuestro certificado y clave pública. Varias entidades de registro de dominios o alojamiento web ofrecen la compra de certificados SSL, en el artículo Certificado SSL, de empresa, «wildcard» y de validación extendida comento con un poco más detalle los varios tipos de certificados y algunas opciones donde obtenerlos o comprarlos.

Dependiendo del tipo de certificado que solicitemos y nos entregue la autoridad de certificado el usuario podrá ver que está simplemente accediendo a un servidor con conexión segura, ver los detalles de nuestro certificado y en algunos casos el usuario podrá ver en la barra de direcciones en verde el nombre de la entidad, que puede darle al usuario más confianza y ver que realmente está accediendo al servidor correcto y no a uno que esté intentando suplantar una identidad. En este último caso la barra de direcciones no tendría en verde el nombre de la entidad, esto es algo que como usuarios debemos comprobar al acceder a determinados sitios de forma segura.

Con la herramienta OpenSSL y los siguientes comandos podemos generar claves y certificados y realizar las conversiones entre formatos que necesitemos. Una vez que disponemos de un certificado y del formato en el que necesitemos podemos hacer uso de él, por ejemplo, en un servidor de páginas web o aplicaciones para proporcionar acceso mediante el protocolo HTTPS y proporcionar seguridad SSL. En otros artículos muestro cómo configurar SSL/TLS en un servidor Tomcat, JBoss, WildFly, Lighttpd, Nginx o Apache, por otro lado usar HTTPS es un requisito para utilizar el protocolo HTTP/2 en un servidor web.

Crear claves y certificados

Crear una clave privada y pública

Para generar un par de claves RSA pública y privada que nos permitan tanto cifrar datos como realizar firmas se emplea el siguiente comando:

1
$ openssl genrsa -out localhost.key 8192
script-1.sh

Para cifrar la clave generada con el algoritmo aes256 y protegerla por una contraseña se puede emplear el siguiente comando, en realidad al generar la clave indicando la misma opción -aes256 en el comando anterior la clave se generará cifrada y protegida por una contraseña. Para cambiar la contraseña es el mismo comando y el segundo comando elimina la contraseña y la descifra:

1
2
$ openssl rsa -aes256 -in localhost.key -out localhost-encrypted.key
$ openssl rsa -in localhost-encrypted.key -out localhost.key
script-12.sh

El contenido de un archivo de clave privada sin cifrar tiene el siguiente aspecto (los tres puntos son líneas de contenido omitidas).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
-----BEGIN RSA PRIVATE KEY-----
MIISKAIBAAKCBAEAyMuPWmmTI4IkfoqQ2TWpqo79GEasdxn9McHb4I5Vk4c3rFIR
ExMozoWmCVvKD6Z9lT9aJ69jlwAR4KGownT4mXN0pRN3mSf6kZ854XssB6o63/0e
/D1xTYdcrP7OKMnHyZwcVKPXEz0RhUsUqH7wzIjwsoXDBDOVFM6EJ2RGo+MuTMDX
wMW3X/DvnDlaxes7ZZizrQ0F+hvopFZowZxRjj/RCJRdAbzNhVEyG+2qtaYlRIC3
mq/eYCJUi+jD1jnFr2daC4zFa6Cr7bGoxrXJlNg4iS1hjciaMV13kXXW1lsWOkPd
exctVEb/nuH64cozPhXJoBjR7rDvXPllnhTay3UnVqK7art1iqKZXmN7FGGM2nJv
w7PIYk25T7H3ucRwfT+svUzdooGNSpojKhFoaAvG4X5Z9wZgtTa24pz/T673DH+J
1Hujco+ufAwJ+ZMZDfnN2g49Y2hqrJmU177e+g6vW5xYAK8raYp6RzTYRuxKLaQg
mi4ctBsycbxETZUk1kSlOB2ebM6+8lArW8VOtCQGdNvvEfydrTHK3hxrEvW8oFAb
j5eU3oWzZL0wTMJ1S/Crbg2eRfCkWPvBdV3e5DUUlqMp2f5urxgOlHmkYEop8gBm
...
...
...
...
...
...
sH+8kfyWZP4x+ivVlTrtJMRPJLKAbIJ2CEN16YQtaE9tjCWcz4JjV2b7k79UEjLg
mVGXSWo8koxl8MJpSFlYJMAlhiLkoanNzW+u+LPvn2Abc6174u5QD+ihk8c=
-----END RSA PRIVATE KEY-----
localhost.key

Exportar la clave pública

El archivo generado al crear el par de claves contiene tanto la clave pública como la privada. La privada no se debe distribuir y se debe mantener protegida de forma que solo la conozca su propietario por ejemplo guardándola en una base de datos de KeePassXC como un archivo adjunto de la aplicación KeePassXC. La clave pública es la que se distribuye a otras personas o entidades. Para extraer la clave pública del archivo generado anterior por OpenSSL usamos el siguiente comando:

1
$ openssl rsa -in localhost.key -pubout > localhost.pub
script-9.sh

También se puede obtener la clave pública en formato OpenSSH y una representación gráfica de la huella digital.

1
$ ssh-keygen -y -f localhost.key > localhost-openssh.pub
script-10.sh
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
$ ssh-keygen -lv -f localhost-openssh.pub
8192 SHA256:mxKfFP7NwwlZsvfxMqG9CQOjJssyOA/v1I67C4j8vwM no comment (RSA)
+---[RSA 8192]----+
|                 |
|                 |
|        . . .    |
|       . . =     |
|      . S * . o  |
|o. E . + * O = + |
|o.o.o + B . X = .|
|  +=o= =     + = |
|   =XO*       o  |
+----[SHA256]-----+
script-15.sh

Obtener la huella digital de la clave pública

La huella digital de una clave pública sirve para comprobar que la clave es la esperada. Son una cadena de números y letras pudiendo estar cada pareja de caracteres separados por :.

1
2
$ openssl dgst -sha256 -c localhost.pub
SHA256(localhost.pub)= a4:39:88:cf:8b:cf:3c:13:23:c1:e6:f8:10:d3:e5:a4:95:6f:30:d6:11:b1:81:4b:ce:3d:c0:e5:1c:57:ca:ff
script-11.sh

Crear un certificado

Un certificado permite utilizar el protocolo seguro HTTPS en un servidor web y contiene la firma de una tercera parte que valida nuestra clave pública como auténtica. Para que esa tercera parte pueda firmar nuestra clave deberemos generar una petición de firma de certificado y enviársela a la autoridad de certificado que nos lo devolverá firmado. La petición firma de certificado se crea con el siguiente comando:

1
$ openssl req -new -key localhost.key -out localhost.csr
script-2.sh

Si no queremos tratar con una autoridad de certificado, ya que cobran por la firma, podemos crear un certificado autofirmado que puede ser suficiente para un entorno de pruebas de un servidor web. El comando para generar el certificado autofirmado es, la opción -subj indica la información del sujeto a autenticar:

1
$ openssl req -new -x509 -days 1825 -subj "/C=ES/ST=Spain/L=/O=/CN=localhost" -key localhost.key -out localhost.crt
script-3.sh

Convertir un certificado a otros formatos

Dependiendo de la autoridad de certificado el certificado puede estar en diferentes formatos, también dependiendo del servidor donde se quiera usar es necesario convertirlo a al formato adecuado. OpenSSL permite para hacer las conversiones entre formatos DER, PEM y PKCS#12.

Convertir un certificado en formato DER (.crt .cer .der) a PEM

1
2
3
$ cat localhost.key localhost.crt > localhost.pem
$ openssl x509 -in localhost.crt -out localhost.pem
$ openssl x509 -inform der -in localhost.cer -out localhost.pem
script-4.sh

Convertir un certificado en formato PEM a DER

1
$ openssl x509 -outform der -in localhost.pem -out localhost.der
script-5.sh

Convertir un certificado en formato PEM y una clave privada a PKCS#12 (.pfx .p12)

1
$ openssl pkcs12 -export -out localhost.p12 -inkey localhost.key -in localhost.crt
script-6.sh

Convertir un archivo en formato PKCS#12 (.pfx .p12) que contiene una clave privada y certificado a PEM

1
$ openssl pkcs12 -in localhost.p12 -out localhost.pem -nodes
script-7.sh

Convertir PKCS#12 a keystore JKS

1
$ keytool -importkeystore -destkeystore localhost.keystore -srckeystore localhost.p12 -srcstoretype pkcs12
script-8.sh

Examinar certificados

Examinar un certificado

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ openssl x509 -text -noout -in localhost.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            49:e5:32:9b:7f:be:bf:a6:90:14:34:5e:24:53:e8:96:51:8d:74:d4
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = ES, ST = Spain, CN = localhost
        Validity
            Not Before: Jul 27 10:40:19 2020 GMT
            Not After : Jul 26 10:40:19 2025 GMT
        Subject: C = ES, ST = Spain, CN = localhost
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (8192 bit)
                Modulus:
                    00:c8:cb:8f:5a:69:93:23:82:24:7e:8a:90:d9:35:
                    a9:aa:8e:fd:18:46:ac:77:19:fd:31:c1:db:e0:8e:
                    ...
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                07:A0:9B:0F:8F:22:9D:AE:CF:F7:46:11:82:B7:7A:0C:43:88:58:8D
            X509v3 Authority Key Identifier: 
                keyid:07:A0:9B:0F:8F:22:9D:AE:CF:F7:46:11:82:B7:7A:0C:43:88:58:8D

            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: sha256WithRSAEncryption
         1b:9d:d1:a5:1a:2d:23:8c:09:8b:08:6c:fb:49:f6:88:e9:51:
         86:ce:19:53:74:ab:90:01:d9:ab:d1:9e:2b:56:ca:7c:a3:53:
         ...
script-13.sh

Examinar el certificado de un servidor web

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ openssl s_client -showcerts -connect duckduckgo.com:443
CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA
verify return:1
depth=0 C = US, ST = Pennsylvania, L = Paoli, O = "Duck Duck Go, Inc.", CN = *.duckduckgo.com
verify return:1
---
Certificate chain
 0 s:C = US, ST = Pennsylvania, L = Paoli, O = "Duck Duck Go, Inc.", CN = *.duckduckgo.com
   i:C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA
-----BEGIN CERTIFICATE-----
MIIGNTCCBR2gAwIBAgIQAx42ydSKbld6na9pgqdX4zANBgkqhkiG9w0BAQsFADBN
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E
...
-----END CERTIFICATE-----
 1 s:C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA
   i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
-----BEGIN CERTIFICATE-----
MIIElDCCA3ygAwIBAgIQAf2j627KdciIQ4tyS8+8kTANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
...
-----END CERTIFICATE-----
---
Server certificate
subject=C = US, ST = Pennsylvania, L = Paoli, O = "Duck Duck Go, Inc.", CN = *.duckduckgo.com

issuer=C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA

---
...
script-14.sh

Autoridad de certificación

Los comandos anteriores permiten generar un certificado autofirmado válido para propocrionar una conexión cifrada entre un servidor y un cliente como es el caso de un servidor web y un navegador web. Pero los certificados autofirmados no permiten todas las validaciones de seguridad, el cliente no puede confiar en que realmente se está conectando al nombre del dominio del servidor que el certificado incluye y por ello en el cliente hay que eliminar la validación de comprobación del certificado. Para mayor seguridad y en un entorno de producción se ha de utilizar una autoridad de certificación, es posible crear una autoridad de certificación propia con comandos de OpenSSL.

Comparte el artículo: