Realizar un login remoto o ssh utilizando autenticación por certificado RSA

ssh

… o lo que es lo mismo realizar un login remoto o ssh sin utilizar usuario y contraeña.

Es el caso en el que queremos realizar un login remoto o login por ssh desde un equipo A a un equipo B (o a ‘n’ equipos) y no queremos utilizar el usuario y contraseña cada vez que realizamos el login.

Los pasos son los siguientes:

  • Relizar el login en el equipo A
  • Generar la clave rsa para autenticación
  • Copiar la clave rsa generada en el equipo B
  • Realizar el login en el equipo B utilizando la clave recién generada

Como podemos imaginarnos necesitamos tener cuentas en ambos equipos para poder realizar estos pasos

Generar las claves para autenticación desde el equipo A

El comando ssh-keygen genera las claves de autenticación que podemos utilizar para el protocolo ssh de versiones 1 y 2. En este caso dejamos en blanco la passphrase.

La cuenta de usuario en este equipo se corresponde con user1.

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user1/.ssh/id_rsa):
/home/user1/.ssh/id_rsa already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user1/.ssh/id_rsa.
Your public key has been saved in /home/user1/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:a3xg5xjLeq8t7qYVwcaa/m4wK/K+zn/ugE5GTxW8WHE user1@equipoa
The key's randomart image is:
+---[RSA 2048]----+
...
...
+----[SHA256]-----+

Copiar la clave recién generada en el equipo B desde la cuenta de usuario del equipo A

La cuenta de usuario en el equipo B se corresponde con user2.

$ ssh-copy-id user2@equipob
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user1/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
user2@equipob's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'user2@equipob'"
and check to make sure that only the key(s) you wanted were added.

Realizar el login ssh desde el equipo A en el equipo remoto B utilizando la clave recién copiada

$ ssh user2@equipob
Welcome to Ubuntu 16.04.1 LTS (GNU/Linux 4.4.0-31-generic x86_64)

A partir de ahora cada vez que realicemos el login en el equipo B no necesitaremos realizar el login ssh con la contraseña.

Anuncios

Verificar la firma de un Certificado con OpenSSL

OpenSSL

Cuando trabajamos con certificados sabemos que estos pueden estar firmados por una CA o bien pueden estar autofirmados.

En cualquiera de los casos la verificación de la firma de un certificado es la misma.

En este pequeño artículo vamos a ver como podemos verificar

  • la firma de un certificado firmado por una CA y
  • la firma de un certificado autofirmado

Para el ejemplo vamos a coger los certificados de la página principal de google, la servida por el protocolo seguro https://www.google.es/.

Utilizando un navegador como Firefox podemos ver la cadena de certificados y exportarlos en formado PEM.

Cadena Certificados Google

Como vemos la cadena de certificados es la siguiente:

  • GeoTrustGlobalCA. Certificado de la CA GeoTrust SSL Certificates que firma con su clave privada el certificado de GoogleInternetAuthorityG2. Es una CA reconocida a nivel mundial. Usa su clave privada para firmar los certificados que le solicitan.
  • GoogleInternetAuthorityG2. Certificado de Google firmado por la anterior CA. Con la clave privada asociada al certificado GoogleInternetAuthorityG2 google firma sus propios certificados. En este caso GoogleInternetAuthorityG2 actua como una CA.
  • google.com. Certificado final utilizado en este site y firmado con la clave privada asociada al certificado GoogleInternetAuthorityG2.

Es suficiente con tener el Certificado de la CA GeoTrustGlobalCA en nuestro almacen de certificados de CAs de confianza para que automáticamente confiemos en todos los certificados firmados por ella.

El paso siguiente es exportar cada uno de ellos. Suponiendo que los hemos exportado en formado PEM (*.crt) vamos a proceder a verificar la firma de cada uno de los certifiados utilizando OpenSSL.

openssl verify -CAfile fichero_CA.pem certificado.pem

Es el comando a utilizar para validar o verificar un certificado, siempre y cuando tengamos el certificado de la CA.

Donde,

  • verify, se utiliza para indicar a openssl que verifique la firma de un certificado
  • CAfile es certificado de la CA con el que vamos a validar el certificado
  • certificado.pem, es el certificado que queremos validar

Verificar el certificado autofirmado de la CA GeoTrustGlobalCA

$ openssl verify -CAfile GeoTrustGlobalCA.crt GeoTrustGlobalCA.crt
GeoTrustGlobalCA.crt: OK

Verificar el certificado de GoogleInternetAuthorityG2 firmado con el certificado de la CA GeoTrustGlobalCA

$ openssl verify -CAfile GeoTrustGlobalCA.crt GoogleInternetAuthorityG2.crt
GoogleInternetAuthorityG2.crt: OK

Verificar el certificado google.com firmado con el certificado de la CA GoogleInternetAuthorityG2

$ openssl verify -CAfile GoogleInternetAuthorityG2.crt google.com.crt
google.com.crt: OK

Si la CA no es la adecuada obtendremos el error de verificación unable to get local issuer certificate

openssl verify -CAfile GeoTrustGlobalCA.crt google.com.crt
google.com.crt: C = US, ST = California, L = Mountain View, O = Google Inc, CN = *.google.com
error 20 at 0 depth lookup:unable to get local issuer certificate

openssl x509 -in fichero_certificado.pem -inform PEM -noout -subject -issuer

En este comando no se utiliza para verificar firmas, pero si puede ser util para identificar en un certificado el emisor o issuer y el propietario o subject del certificado.

  • El issuer es el emisor del certificado, es decir, el que lo firma con su clave privada.
  • El subject es el propietario del certificado, es decir, el que lo crea y solicita a la CA que lo firme.

Si un certificado es autofirmado, ambos tendrán el mismo valor.

Siguiendo con los certificados de este ejemplo, vamos a ver como el primero de la cadena GeoTrustGlobalCA es autofirmado:

Obtención del issuer y el subject de un certificado

$ openssl x509 -in GeoTrustGlobalCA.crt -inform PEM -noout -subject -issuer
subject= /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
issuer= /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA

Como vemos ambos son el mismo. Se trata de un certificado autofirmado.

Sin embargo los otros dos certificados no lo son, y podemos ver quién lo firma y quién lo solicita:

$ openssl x509 -in GoogleInternetAuthorityG2.crt -inform PEM -noout -subject -issuer
subject= /C=US/O=Google Inc/CN=Google Internet Authority G2
issuer= /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA

$ openssl x509 -in google.com.crt -inform PEM -noout -subject -issuer
subject= /C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com
issuer= /C=US/O=Google Inc/CN=Google Internet Authority G2

Importar un Certificado de una CA en el cacerts de la Jdk

Java

Es habitual encontrarnos en situaciones donde una empresa tiene su propia autoridad de certificación (Certificate authority o CA) con la que firma los certificados de sus servidores o bien nos encontramos con servicios REST o web services de sites cuyo certificado esta firmado por una CA que no la tenemos en nuestro almacén de CAs de confianza.

En estos casos para que nuestras aplicaciones puedan establecer una conexión segura a estos servicios, necesitamos incorporar el certificado de la CA en nuestro almacén de CAs de confianza.

De esta forma, siempre y cuando nos encontremos con un certificado firmado por cualquiera de esas nuevas CAs, confiaremos automáticamente en ellos.

Como sabemos una CA firma los certificados que emite con su clave privada y es mediante el certificado de la CA con lo que podemos verificar la firma. Esta firma va incluida en el certificado emitido. Por ese motivo incorporamos el certificado de la CA entre los que confiamos.

En la Jdk el almacen de CAs de confianza lo vamos a encontrar en:

$JAVA_HOME/jre/lib/security/cacerts

Para incorporar el Certificado de la CA en el cacerts necesitamos importarlo.

Importar un certificado de una CA en nuestro almacén de CAs de confianza o cacerts

$JAVA_HOME/bin/keytool -import -alias NuevoCA -file NuevoCertificadoCA.crt -keystore $JAVA_HOME/jre/lib/security/cacerts

La contraseña por defecto del cacerts es: changeit.

Este comando nos pedirá confirmación de que queremos importar este nuevo certificado en el almacén de CAs.

Importar un certificado de una CA en un almacén de CAs de confianza

keytool -import -trustcacerts -alias NuevoCA -file NuevoCertificadoCA.crt -keystore cacerts_app

-trustcacerts: Se utiliza cuando el -keystore no es el cacerts, y queremos que al importar el certificado, keytool tenga en cuenta los Certificados de las CAs que tenemos en el fichero cacerts

Herramienta gráfica para administrar un almacén de certificados

Si no queremos utiliza la línea de comando siempre podemos recurrir a alguna de las herramientas gráficas existente para manejar y administrar certificados.

Portecle es una de ellas. Muy simple y sencilla de utilizar.

Portecle

Excepción habitual que pretendemos evitar al incorpotar el Certificado de la CA

Cuando accedemos a un servicio por conexión segura y el certificado es autofirmado o no tenemos el certificado de la CA que lo firma en nuestro cacerts, obtendremos la siguiente excepción:

Exception in thread "main" javax.xml.ws.WebServiceException: Fallo al acceder al WSDL en: https://localhost/myservice. Ha fallado con: 
    sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target.
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(RuntimeWSDLParser.java:250)
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:231)
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:194)
    at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:163)
    ...
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1937)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
    ...

Incorporando el Certificado de la CA evitaremos este tipo de excepciones.

Crear una petición de firma de certificado o CSR – Certificate Signing Request – con OpenSSL

PKI

Un CSR o Certificate Signing Request es una petición de firma de certificado que enviaremos a una CA pública para que verifique nuestra identidad y lo firme. Como resultado obtendremos un certificado fimado por esa CA.

¿En qué consiste un CSR?

Un CSR esta formado por la clave pública, información adicional que identifica a la entidad a la que pertenece y todo ello firmado con la clave privada.

Recordemos que cuando creamos una clave privada, estamos creando también la clave pública asociada a esa clave privada.

Con OpenSSL esto se realiza en un solo paso como ya hemos visto en el artículo Creación de una clave pública y privada con OpenSSL de este blog.

Una vez hemos creado un CSR lo enviaremos a una CA, y esta CA una vez ha identificado quienes somos procederá a firmarlo y nos devolverá el certificado, junto con otra serie de información entre la que se encuentra el identificador de la CA.

A partir de ese momento, ese certificado lo podemos utilizar por ejemplo en un servidor. Cuando un navegador se conecta a nuestro servidor, si en su almacen de certificados de confianza tiene el de la CA que ha firmado nuestro certificado, automaticamente confiará en nuestro certificado y comenzara la conexión segura (Https).

¿En qué consiste un certificado?

El proceso final de un CSR es su firma por parte de la CA y como resultado obtenemos el certificado. Este certificado contiene la misma información del CSR, pero además incluye entre otros datos, el identificador de la CA y su firma.

Formato de un CSR

Suele utilizarse el formato PEM, que no es otro que la representación en Base64 del certificado.

Si lo editamos en un fichero de texto veremos las cabeceras de comienzo y fin del certificado.

-----BEGIN CERTIFICATE REQUEST-----

Representación en Base64 del certificado

-----END CERTIFICATE REQUEST-----

Crear una petición de firma de certificado o CSR

Partimos de la clave pública y privada creada en el artículo de este blog Creación de una clave pública y privada con OpenSSL.

Pasos para crear un CSR

$ openssl req -new -key key.pem -out cert.csr

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:ES
State or Province Name (full name) [Some-State]:Madrid
Locality Name (eg, city) []:Madrid
Organization Name (eg, company) [Internet Widgits Pty Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (e.g. server FQDN or YOUR name) []:mydomain.com
Email Address []:admin@mydomain.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:.
An optional company name []:.

Como vemos la creación del CSR se realiza en un solo paso. Toda la información que rellenamos, es la que finalmente nos identifica a nosotros como entidad.

Si vamos a utilizar el certificado devuelto por la CA en un servidor el Common Name debe ser el dominio de nuestro servidor.

Al estar en formato PEM podemos editar el CSR en un editor de textos normal:

-----BEGIN CERTIFICATE REQUEST-----
MIICrjCCAZYCAQAwaTELMAkGA1UEBhMCRVMxDzANBgNVBAgMBk1hZHJpZDEPMA0G
A1UEBwwGTWFkcmlkMRUwEwYDVQQDDAxteWRvbWFpbi5jb20xITAfBgkqhkiG9w0B
CQEWEmFkbWluQG15ZG9tYWluLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAMAtq8PGcdoudwcrsEih9l4M2JhhcFOVBeZwYs7Jn9u29YhQtiqh4g2D
oirpV9MK5GJ+DPA48OSKPmBHKJ0M8nt7YMkmEFm0jw1P7PIENtuPIbqAIGUauL0G
xx/0kImzXfXfTbJyyCtfrXxNq/S7dCTuP1Jc+DxRdMLttRKsa11K272BWTX3NK/+
L0OcvFyuUSA+/ZtjXoSmx3oyRKtmm4JFV4qsBDyMcv05KrEYKkXMeknPykl541Ks
FdxjrytWAcBPHLEITTj6j9r1IcRIwM5EjN7S7yP/2gNlT7B/p7x41o3tUzFUdcyg
kwLy4fxmeCqYV5WOiwLh275yDkyR4OkCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4IB
AQAOVGldwOKjJtqP4oG24AiQAiI7TjSj/6kSvC8yYkQarWT1nD3EvIqCwUgT7Zn9
4mM+XWtkmMSDp/FwRgeafptA/90idyPwp67tPrOutcWnbH0NGBEkJgpTQ9dx5Wr5
JiU1KN+hXZbgyPojtKJSLKAMv3JOHfBLmqAc6ISXWyCtsb+Y3rWygrl/CETvesQw
v+72UsDCMj50NUqAjRKxvXpIkQ/udG7DeFDThDpiiNSPi3L0B6Vw+d0zZ/rDCWkw
0aP0CpfEpZiltww0RENykIhp/Vl5A7hJ/5ync3gS70jE6tB5N9jcORJlG9IX0geM
ehfHONXqbcIIxtlXh/stipjJ
-----END CERTIFICATE REQUEST-----

Finalmente enviaremos ese CSR a una CA pública para que nos lo firme.

Verificación de los datos del CSR

$ openssl req -text -in cert.csr
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=ES, ST=Madrid, L=Madrid, CN=mydomain.com/emailAddress=admin@mydomain.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:c0:2d:ab:c3:c6:71:da:2e:77:07:2b:b0:48:a1:
                    ...
                    78:2a:98:57:95:8e:8b:02:e1:db:be:72:0e:4c:91:
                    e0:e9
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha1WithRSAEncryption
         0e:54:69:5d:c0:e2:a3:26:da:8f:e2:81:b6:e0:08:90:02:22:
         ...
         17:d2:07:8c:7a:17:c7:38:d5:ea:6d:c2:08:c6:d9:57:87:fb:
         2d:8a:98:c9
-----BEGIN CERTIFICATE REQUEST-----
MIICrjCCAZYCAQAwaTELMAkGA1UEBhMCRVMxDzANBgNVBAgMBk1hZHJpZDEPMA0G
...
ehfHONXqbcIIxtlXh/stipjJ
-----END CERTIFICATE REQUEST-----

Vemos que los datos introducidos son correctos, y además, vemos otra serie de información adicional como es el la longitud de la clave pública utilizado (2048 bits), el algoritmo Signature Algorithm utilizado para firmar el CSR con nuestra clave privada, la clave pública etc.

Extracción de la clave pública de un CSR

Como hemos dicho dentro de un CSR va la clave pública asociada a nuestra clave privada. La podemos extraer directamente del CSR con OpenSSL

$ openssl req -in cert.csr -noout -pubkey

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwC2rw8Zx2i53ByuwSKH2
XgzYmGFwU5UF5nBizsmf27b1iFC2KqHiDYOiKulX0wrkYn4M8Djw5Io+YEconQzy
e3tgySYQWbSPDU/s8gQ2248huoAgZRq4vQbHH/SQibNd9d9NsnLIK1+tfE2r9Lt0
JO4/Ulz4PFF0wu21EqxrXUrbvYFZNfc0r/4vQ5y8XK5RID79m2NehKbHejJEq2ab
gkVXiqwEPIxy/TkqsRgqRcx6Sc/KSXnjUqwV3GOvK1YBwE8csQhNOPqP2vUhxEjA
zkSM3tLvI//aA2VPsH+nvHjWje1TMVR1zKCTAvLh/GZ4KphXlY6LAuHbvnIOTJHg
6QIDAQAB
-----END PUBLIC KEY-----

Extracción de la clave pública asociada a la clave privada

La clave pública sabemos que se puede extraer directamente de la clave privada, ya que lo hemos hecho en anteriores artículos de este blog, el comando es el siguiente:

$ openssl rsa -in key.pem -pubout
writing RSA key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwC2rw8Zx2i53ByuwSKH2
XgzYmGFwU5UF5nBizsmf27b1iFC2KqHiDYOiKulX0wrkYn4M8Djw5Io+YEconQzy
e3tgySYQWbSPDU/s8gQ2248huoAgZRq4vQbHH/SQibNd9d9NsnLIK1+tfE2r9Lt0
JO4/Ulz4PFF0wu21EqxrXUrbvYFZNfc0r/4vQ5y8XK5RID79m2NehKbHejJEq2ab
gkVXiqwEPIxy/TkqsRgqRcx6Sc/KSXnjUqwV3GOvK1YBwE8csQhNOPqP2vUhxEjA
zkSM3tLvI//aA2VPsH+nvHjWje1TMVR1zKCTAvLh/GZ4KphXlY6LAuHbvnIOTJHg
6QIDAQAB
-----END PUBLIC KEY-----

Verificación de la firma del CSR

Como hemos dicho, el CSR lo hemos firmado con nuestra clave privada. Como la firma se encuentra en el CSR al igual que la clave pública, podemos verificarlo muy facilmente

$ openssl req -in cert.csr -noout -verify

verify OK

Firmar nosotros mismos el CSR

Si al final decidimos no enviar el CSR a una CA debido a que lo vamos a utilizar de forma interna en nuestra intranet, podemos firmarlo nosotros mismos.

$ openssl x509 -req -days 3650 -in cert.csr -signkey key.pem -out cert.crt

Signature ok
subject=/C=ES/ST=Madrid/L=Madrid/CN=mydomain.com/emailAddress=admin@mydomain.com
Getting Private key

Crear un certificado autofirmado

Si desde el principio sabemos que no vamos a enviar el CSR a una CA, podemos crear directamente el certificado, creando con OpenSSL un certificado autofirmado:

$ openssl req -new -x509 -days 3650 -key key.pem -out fd.crt

Comprobación de los datos de un certificado

Una vez tenemos el certificado devuelto por la CA o bien hemos generado nuestro certificado autofirmado, podemos verificar la información del certificado. Veremos la información de expiración, la entidad que lo firma Issuer, la clave pública, etc.

$ openssl x509 -text -in cert.crt
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            e8:56:61:0b:7e:90:63:05
    Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=ES, ST=Madrid, L=Madrid, CN=mydomain.com/emailAddress=admin@mydomain.com
        Validity
            Not Before: Oct 28 11:28:34 2015 GMT
            Not After : Oct 25 11:28:34 2025 GMT
        Subject: C=ES, ST=Madrid, L=Madrid, CN=mydomain.com/emailAddress=admin@mydomain.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:c0:2d:ab:c3:c6:71:da:2e:77:07:2b:b0:48:a1:
                    f6:5e:0c:d8:98:61:70:53:95:05:e6:70:62:ce:c9:
                    9f:db:b6:f5:88:50:b6:2a:a1:e2:0d:83:a2:2a:e9:
                    57:d3:0a:e4:62:7e:0c:f0:38:f0:e4:8a:3e:60:47:
                    28:9d:0c:f2:7b:7b:60:c9:26:10:59:b4:8f:0d:4f:
                    ec:f2:04:36:db:8f:21:ba:80:20:65:1a:b8:bd:06:
                    c7:1f:f4:90:89:b3:5d:f5:df:4d:b2:72:c8:2b:5f:
                    ad:7c:4d:ab:f4:bb:74:24:ee:3f:52:5c:f8:3c:51:
                    74:c2:ed:b5:12:ac:6b:5d:4a:db:bd:81:59:35:f7:
                    34:af:fe:2f:43:9c:bc:5c:ae:51:20:3e:fd:9b:63:
                    5e:84:a6:c7:7a:32:44:ab:66:9b:82:45:57:8a:ac:
                    04:3c:8c:72:fd:39:2a:b1:18:2a:45:cc:7a:49:cf:
                    ca:49:79:e3:52:ac:15:dc:63:af:2b:56:01:c0:4f:
                    1c:b1:08:4d:38:fa:8f:da:f5:21:c4:48:c0:ce:44:
                    8c:de:d2:ef:23:ff:da:03:65:4f:b0:7f:a7:bc:78:
                    d6:8d:ed:53:31:54:75:cc:a0:93:02:f2:e1:fc:66:
                    78:2a:98:57:95:8e:8b:02:e1:db:be:72:0e:4c:91:
                    e0:e9
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha1WithRSAEncryption
         38:fb:46:0b:8b:0a:10:3f:d1:e7:51:53:c3:8d:67:ad:d3:93:
         0e:48:52:94:03:8a:a5:06:77:0b:8c:9e:5a:4c:17:cf:a9:76:
         dd:70:69:31:08:f7:d4:de:9e:6d:90:e2:e2:7b:ab:8b:23:1b:
         4d:95:34:19:35:a7:08:29:93:b7:f2:6d:9b:17:66:cc:8f:98:
         a1:7b:65:49:af:aa:4e:57:c0:1c:e0:69:bb:cf:57:59:1d:b7:
         0b:f5:ad:68:3d:f5:f9:fe:23:af:1a:fc:59:31:05:fa:7b:4d:
         5f:40:d9:25:43:f3:a4:ff:09:cb:52:86:ae:95:36:72:fb:03:
         25:c7:ac:ea:9f:d7:5e:a8:b3:32:71:94:a2:58:8f:bf:a2:ee:
         08:ea:f5:d4:18:1d:8b:d8:ff:fb:47:1c:8a:5e:19:18:c7:ad:
         e6:04:88:80:70:22:f7:eb:17:71:9c:67:1c:76:9d:4c:de:a5:
         6f:9b:6e:0b:c8:73:e8:ed:b9:cb:6a:81:a7:35:d3:2a:47:da:
         38:48:1c:96:5d:ba:b9:3f:3b:4c:41:4b:8b:d5:1f:68:19:8f:
         bf:fc:7d:ed:75:f9:da:7f:d4:bd:df:60:77:de:0b:db:fd:b1:
         4a:69:73:f6:f4:c1:bb:46:0e:35:58:aa:2d:5e:99:44:54:c4:
         b7:6c:d5:53
-----BEGIN CERTIFICATE-----
MIIDTjCCAjYCCQDoVmELfpBjBTANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJF
UzEPMA0GA1UECAwGTWFkcmlkMQ8wDQYDVQQHDAZNYWRyaWQxFTATBgNVBAMMDG15
ZG9tYWluLmNvbTEhMB8GCSqGSIb3DQEJARYSYWRtaW5AbXlkb21haW4uY29tMB4X
DTE1MTAyODExMjgzNFoXDTI1MTAyNTExMjgzNFowaTELMAkGA1UEBhMCRVMxDzAN
BgNVBAgMBk1hZHJpZDEPMA0GA1UEBwwGTWFkcmlkMRUwEwYDVQQDDAxteWRvbWFp
bi5jb20xITAfBgkqhkiG9w0BCQEWEmFkbWluQG15ZG9tYWluLmNvbTCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMAtq8PGcdoudwcrsEih9l4M2JhhcFOV
BeZwYs7Jn9u29YhQtiqh4g2DoirpV9MK5GJ+DPA48OSKPmBHKJ0M8nt7YMkmEFm0
jw1P7PIENtuPIbqAIGUauL0Gxx/0kImzXfXfTbJyyCtfrXxNq/S7dCTuP1Jc+DxR
dMLttRKsa11K272BWTX3NK/+L0OcvFyuUSA+/ZtjXoSmx3oyRKtmm4JFV4qsBDyM
cv05KrEYKkXMeknPykl541KsFdxjrytWAcBPHLEITTj6j9r1IcRIwM5EjN7S7yP/
2gNlT7B/p7x41o3tUzFUdcygkwLy4fxmeCqYV5WOiwLh275yDkyR4OkCAwEAATAN
BgkqhkiG9w0BAQUFAAOCAQEAOPtGC4sKED/R51FTw41nrdOTDkhSlAOKpQZ3C4ye
WkwXz6l23XBpMQj31N6ebZDi4nuriyMbTZU0GTWnCCmTt/JtmxdmzI+YoXtlSa+q
TlfAHOBpu89XWR23C/WtaD31+f4jrxr8WTEF+ntNX0DZJUPzpP8Jy1KGrpU2cvsD
Jces6p/XXqizMnGUoliPv6LuCOr11Bgdi9j/+0ccil4ZGMet5gSIgHAi9+sXcZxn
HHadTN6lb5tuC8hz6O25y2qBpzXTKkfaOEgcll26uT87TEFLi9UfaBmPv/x97XX5
2n/Uvd9gd94L2/2xSmlz9vTBu0YONViqLV6ZRFTEt2zVUw==
-----END CERTIFICATE-----

Igualmente podríamos hacer las mismas operaciones que hemos visto en los puntos anteriores, como extraer la clave pública del certificado con

$ openssl x509 -in cert.crt -noout -pubkey

Creación de una clave pública y privada con OpenSSL

PKI

La clave pública y privada se utiliza en la infraestructuras de clave pública PKI para el cifrado y descrifrado de datos, así como para la firma digital y su verificación.

A la hora de crear una clave pública y privada debemos tener en cuenta los siguientes puntos.

Algoritmos de generación de clave

Los algoritmos más utilizados y soportados son RSA, DSA y ECDSA.

DSA. Conocido como Digital Signature Algorithm. Se encuentra limitado a la generación de claves de 512 bits y 1024 bits.

Se utiliza para la firma digital y verificación de firma.

RSA. Su nombre es debido a sus creadores Ron Rivest, Adi Shamir y Leonard Adleman. Es el más utilizado y soportado ya que no está limitado a 1024 bits, lo que le hace ser más seguro para la firma digital que DSA.

Se utiliza para firma digital, y para cifrar y descifrar datos.

ECDSA. Conocido como Elliptic Curve Digital Signature Algorithm. Es más reciente que el RSA. Es más seguro que el RSA ya que con claves más pequeñas se consigue el mismo nivel de seguridad que claves mas grandes en el RSA. Al tener claves más pequeñas también es mejor algoritmo ya que mejora el redimiendo de las aplicaciones de cifrado, descifrado y firma digital.

Se utiliza para la firma digital y verificación de firma, y para el cifrado y descifrado de datos.

Seguridad de la clave

La seguridad de la clave la marcan dos factores:

Tamaño de la clave. A día de hoy la longitud o tamaño de una clave debe ser como mínimo de 2048 bits. Es la longitud recomendada, ya que tamaños de claves inferiores pueden ser obtenidas a partir de un certificado utilizando fuerza bruta.

Passphrase. Se recomienda que las claves sean protegidas por una contraseña. No obstante si es una clave que va a ser utilizada junto con su certificado en un servidor web o proxy reverso, no es necesario que la utilicemos, ya que cada vez que el servidor es reiniciado, tendríamos que introducir a mano dicha contraseña, lo cual es poco práctico.

A continuación vamos a crear una clave utilizando el algoritmo RSA.

Esta clave la utilizaremos en otros artículos para crear un certificado autofirmado y para crear una petición de firma de un certificado, que sería el que enviaríamos a un CA para que nos lo firme.

Generar clave pública y privada en formato PEM sin contraseña

$ sudo openssl genrsa -out key.pem 2048
Generating RSA private key, 2048 bit long modulus
.....+++
.........................+++

Generar clave pública y privada en formato PEM con contraseña

Siempre que utilicemos la clave openssl nos pedirá la contraseña.

$ sudo openssl genrsa -aes128 -out key.pem 2048
Generating RSA private key, 2048 bit long modulus
...............................................................................+++
..........................+++
Enter pass phrase for key.pem:
Verifying - Enter pass phrase for key.pem:

Clave privada en formato PEM sin contraseña

Al estar en formato PEM podemos ver la clave en cualquier editor de textos. El algoritmo RSA utilizado para la generación de clave viene informado en la cabecera de la clave.

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAwC2rw8Zx2i53ByuwSKH2XgzYmGFwU5UF5nBizsmf27b1iFC2
KqHiDYOiKulX0wrkYn4M8Djw5Io+YEconQzye3tgySYQWbSPDU/s8gQ2248huoAg
ZRq4vQbHH/SQibNd9d9NsnLIK1+tfE2r9Lt0JO4/Ulz4PFF0wu21EqxrXUrbvYFZ
Nfc0r/4vQ5y8XK5RID79m2NehKbHejJEq2abgkVXiqwEPIxy/TkqsRgqRcx6Sc/K
SXnjUqwV3GOvK1YBwE8csQhNOPqP2vUhxEjAzkSM3tLvI//aA2VPsH+nvHjWje1T
MVR1zKCTAvLh/GZ4KphXlY6LAuHbvnIOTJHg6QIDAQABAoIBAGfRRFVCwwamy05o
X5cdR8aPEgNfwBqnCsTuObKUYXOEZyf40jA9u6ypS9X6sKMl4zMB/WNYn2oW9JN2
XY5aDDSA9kwz7+lGDXGXl902QZxiuknSJa34vYwAOVod+GcrKrtEouif8VrdGQ9p
tldDXP8GZdbMup17M6SKXaN02ZtPgbbNPTkweeVQVf399o7YIGfGnijs0SJ08yF9
NY6trH7rTAPf5bG3lbaEd2JuwfHw5hznp0mdimqeU4lW3LHFA3J3g7Myk9bprtp8
PnZdVypNdjRFHLhBhu67WlMgvntWw8dMQvOP7Xv9TLC+1KIAzA0wFsSfS14+AI4x
A8yUWzECgYEA3x76Gv4Rx9TMLMQUlsx1M3o4yDj5VD54bOkIxwH/1kspds1zBRLE
domCcIfrD04U4sX7vu74tTsmWtGlwZQ9Q+NhsdQZKMBWX27+JohqPkrYmmUyBTxE
zP+0yXLpL7MzjW7jzdeOfrXQWx0E73f4uqd8muPIPYXuwm6dSAZ2HdsCgYEA3H9q
FpNtFQDWW1zS/wgeoKSOZPAHr6JB+zB4FRNwlNKD5Mtd5DlVKjGFg9JrdhIpUVzp
6LG7My5lNI0U8YxTKGuOPoEHRX2pusod2PDfXc/yudwWn9KhHM39zLzT+iHu5e2q
M9E0paRJMxUFIkN8TYG/eN07PVZ4wxcSguZmcYsCgYBpQc7RTwyKTfwoHjRsU3Xy
2/TPl/kfYf0ju+e1Il9T889SyWc6fHkMRqCvf59HcBlwReAWWdwgexAEBiUBJnKk
hS9AWgOoctwMV2s0OGSOkHaQl666Q41dfEAITNpu80YdsbNsFwWVByaM5Sq/4cQI
Ih0pYM3FIFrbhJ1ULiAowwKBgQDHqViXOMf9zNRNxrAI34FcVaXbIL7U+0hj/G/A
Jeo72KQ1+TD8CC5mFpGf3FoSgD+JvWjRnJ62qbxa6aWdVEO4xiv3zT6YXkHjMkH0
v6iDelmAkxqpfkEFpEG9sv7/8NoyuhL0+OuDUlA2QUJ01Ecqp+KJv0p1MGgJwEqy
3Y7GIQKBgDjXGqXEFH5KxpulhlKQyaFCT5C2gWz+ZKfzbL6ZnP/PcXlCbBk4hnWg
gTQmxMty0M4f1YntwKMl9I0qv6SRiNAEJEOH0XPOlsASN/U6ekvWAwkHpr+DrNjk
xTBUHfq8vK+A2yQfhzoV7EnCbk/B9vn7Vw4dH0vhMgQG+aJaQn24
-----END RSA PRIVATE KEY-----

Clave privada en formato PEM con contraseña

Igualmente, como tenemos la clave en formato PEM, podemos verla con cualquier editor de textos. Como la clave se ha protegido con contraseña, vamos a ver como antes de la clave, tenemos una serie de metadatos informando del tipo de algoritmo utilizado para proteger la clave. En este caso es AES128.

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,5274591E525CB2302A38501B45059542

yAjd+MiPw6EG+MONq34zczDbRkmepxYqHQRVyZgfsu5oeCJ5VpWoUY/4RCbXOzK/
ZIL6Hivq8oJkWaF0h5cW6SlZeqOFdVlgxAGa547gRLwCMQVwaZEaNt1l8x1PhiSX
waGyKVTv9Ui9ZOlBMlgQWW/iyPFMKIAtgtNQf0S/b0hbA0YsQgW1c+v0jrmeYP58
MWNGkVV07W/Wo6Z4XyaYkXURDLb5Ds4nsqrGk+EubUGSr7MezttGleLo/gPSgMzA
Ueozs2KMSUHYwLR30fv3g64nyg+WXKr8JJwOT2N1Z7g2caDJNq/jDxW4/zTgrYCG
UXZ824hG7uMNh/cscHyJE5s+rkGH9Ix1/27etiE+sz/m/ODrDcZdVl8xy84wx3kf
D0R4feNSja26A+I/yxPh4SC58+wwmZwOLTOrFInZy+uUEOO0t9e423AlJGjAsrox
FxVViuero4TiQaxDw7HPrBI3E9kyco5FLi8O85RP1b6rl/PXcvgPHF04RShbaPTu
/L0RthPVgc7HGwjojPGwZLtcngvVGAnR3ty7btFjYcvJl0KH+jicXyIHl8f5mMTj
8WjCRic/7oKseSBixGFrahYeD51WUwwp85CJgKn/Wv9kjW+cEqowF2MPOpSteRq8
/kLkjjjrWrBmVDqv9w3w4mK+WBEhj73LLy1tpHWWM4i55xQy5RRP1l7pehK3cOiw
54cfxC5tnAnWpryTKbU1S7aCRJBFLsspi51Rd001NHS3CIBC0gVziL15RnqsbNsK
YYa/CU8FnfKUIS8Kf4udO64GUSRFALcoob9p8k3A+QtAp+6VjO5UaHCtSYV5epST
wReuz8jvusZQdra//N3goDFu1SB6U6Ea6lS/z/xxggU8nV6a4Pgo3OGxaAH6cGx3
EAQRndUWqS3i2dQjsgcdE4g736JuQ2cD6NF+OlHpZSnESUjb+M1P6hlr44Jjk1Gm
2rZrNvlDNgiVhe5yCsjJ+1atT2TGX+xJK6EOVm3ReVo+BIiqwHua00Eui3LQpKDX
EyxtCnGXyNZrToOvRm+Fk/RDhljykAzSYUxWHzT6n5cc7dXKFiWscO4Ue48bqw/h
0+HepzB7Kf3yNoP6Yr+1lLijxEbNcqNb+H6sWqzesJFYCw0ugLhs+4qVDIgPfl11
apljLTEKqvcqn/IMguEmPWRsDU/i3thTRrH7jKWOPAvE9taMXXNqjXP/n9WqqJNi
6EH0Mm7ia0lL8QasBrnqyfGN/U9m3m7Q/cSCPuzWG+E+69oitCU2LkyGU1rkzZDO
DlpOAFeYoCsbd4HG9ZCehQGIpKG8oDsRw4GlJxTSGVHyJal0vShPGSghj6VsEdd/
7+9Nofvbau4UHjB46KjgxF65KtZJduPVA9N5dJZ7U4hHt3RHgNonNXBEa1DGgsos
pz9RVujNEq3HX1g9Xt1rK50EyYUpT+K+zeL/uuqWrRhupYFylJCibs0GGeR1iZM1
ZdSvEQy0VkYR1eIp9qmL+c8AbE1fTVpi+C7Sy2ZEoCebj0RNpa5xz5Qcxjtj+VJD
rthAChc+71cYg0nWojvGJ/843Ho5QA2yYzAX8Z/ARgmsL/CiJlY0v4I4KM9nMBmI
-----END RSA PRIVATE KEY-----

Obtención o separación de la clave pública en formato PEM

Si lo necesitamos podemos obtener la clave pública asociada a nuestra clave privada.

$ openssl rsa -in key.pem -pubout -out key.public.pem
writing RSA key

Si editamos la clave pública con un editor de textos, vemos como la cabecera y pie de la clave tiene un formato distinto. En este caso nos indica que se trata de una clave pública.

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwC2rw8Zx2i53ByuwSKH2
XgzYmGFwU5UF5nBizsmf27b1iFC2KqHiDYOiKulX0wrkYn4M8Djw5Io+YEconQzy
e3tgySYQWbSPDU/s8gQ2248huoAgZRq4vQbHH/SQibNd9d9NsnLIK1+tfE2r9Lt0
JO4/Ulz4PFF0wu21EqxrXUrbvYFZNfc0r/4vQ5y8XK5RID79m2NehKbHejJEq2ab
gkVXiqwEPIxy/TkqsRgqRcx6Sc/KSXnjUqwV3GOvK1YBwE8csQhNOPqP2vUhxEjA
zkSM3tLvI//aA2VPsH+nvHjWje1TMVR1zKCTAvLh/GZ4KphXlY6LAuHbvnIOTJHg
6QIDAQAB
-----END PUBLIC KEY-----

Crear un almacen de certificados de confianza con los certificados de las principales CAs

PKI

No es una tarea que tengamos que realizar con frecuencia ya que la mayoría de las aplicaciones que lo necesitan vienen con este almacen de certificados confianza o trust store.

Por ejemplo, la Jsdk viene con su almacen de certificados de confianza y lo podemos encontra en el fichero

$JAVA_HOME/jre/lib/security/cacerts

¿Qué es un almacen de certificados de confianza?

Es un fichero donde tenemos todos los certificados públicos de las principales Autoridades de Certificación también conocidas como CAs o Certification Authority.

¿Y qué es una CA?

Es una autoridad responsable de firmar los certificados de entidades o empresas, que prestan una serie de servicios a otras entidades o empresas. Estas autoridades nos aseguran que los certificados firmados por ellos pertenecen a los entidades o empresas que han pedido que se los firmen. Una vez les han firmado el certificado, estas entidades o empresas pueden comenzar a prestar su servicios utilizando ese certificado firmado por la CA. Un caso muy común son todos los servicios prestados utilizando el protocolo Https.

¿Y qué conseguimos con esto?

Pues que cada vez que accedemos desde nuestro navegador o desde cualquier aplicación a un servidor o servicio con un certificado firmado por una de estas CAs, y además tenemos este almacen de certificados de confianza que hemos mencionado, nuestro navegador o aplicación confia en ese certificado y comienza el establecimiento de la conexión segura y cifrado de datos.

La confianza se basa en la comprobación de la firma del certificado recibido utilizando el Cetificado de la CA que tenemos en nuestro almacen de certificados de confianza. Esto se realiza de forma transparente al usuario, en el caso de un navegador lo hace el navegador automáticamente. Si no tenemos el certificado de la CA en el almacen de certificados de confianza, el navegador no avisaría de esta situación.

Recordemos que un certificado firmado por una CA, puede ser comprobado utilizando el certificado público de esa CA.

Pasos para crear u obtener este almacen de certificados de confianza

Mozilla mantiene una lista actualizada de todas las principales CAs que existen en la actualidad, pero lo mantiene en un formato propietario. La lista de todas las CAs que mantiene la podemos encontrar aquí

Listado de las CAs mantenidas por Mozilla

El fichero en formato propietario lo podríamos descargar de este enlace

Trust Store en formato de Mozilla

pero lo que realmente nos interesa es poder obtener ese mismo fichero en formato PEM, es decir, en un fichero ASCII codificado en Base64. Este fichero lo tenemos mantenido y actualizado por la gente de curl – http://curl.haxx.se/docs/caextract.html y lo podemos descargar desde aquí

Almacen de Certificados de confianza en formato PEM

Una vez hemos conseguido tener este fichero, ya tenemos nuestro almacen de certificados de confianza de las principales autoridades de certificación o CAs, y lo podremos utilizar en cualquier software o aplicacion que desarrollemos, al igual que lo hace la jsdk.

Tipos de formatos de los certificados, clave pública y clave privada utilizados en el estándar X.509

PKI

X.509 es un conjunto de estándares y protocolos utilizados en la infraestructura de clave pública conocida también como Public Key Infrastructure o PKI.

Entre estos estándares y protocolos se definen el formato que deben tener los certificados y las claves públicas y privadas. Estos certificados y las claves en función del formato elegido se pueden almacenar en un mismo fichero o en diferentes.

En este artículo vamos a ver un breve resumen de los formatos más utilizados en X.509.

Clave en formato binario o DER

Se utiliza para almacenar la clave privada en formato binario o raw, utilizando el encoding DER ASN.1.

La extensión de estos ficheros suele ser *.der.

Clave en formato binario o PKCS#8

Es una alternativa al formato anterior, donde también se almacena la clave privada en formato binario o raw pero utilizando el estándar definido en la RFC 5208.

Clave en formato ASCII o PEM

Se utiliza para almacenar la clave privada en formato ASCII codificado en Base 64.

Este tipo de ficheros viene normalmente protegido con una contraseña y con información adicional informando del tipo de clave y algoritmo utilizado.

Al ser un fichero de texto donde la clave viene en Base 64, si lo abrimos podemos ver su contenido.

La clave viene entre dos cabeceras, que en función del algoritmo utilizado pueden variar ligeramenteme, por ejemplo

-----BEGIN RSA PRIVATE KEY-----

Clave privada con los metadatos

-----END RSA PRIVATE KEY-----

Si en vez de una clave privada lo que tenemos es una clave pública, las cabeceras serán distintas

-----BEGIN PUBLIC KEY-----

Clave publica en Base64

-----END PUBLIC KEY-----

La extensión de estos ficheros suele ser *.pem.

Certificado en formato binario o DER

Se utiliza el encoding DER ASN.1 para almacenar el certificado que estará en formato binario o raw.

La extensión de estos ficheros suele ser *.der.

Certificado en formato ASCII o PEM

Se utiliza el encoding base 64 para almacenar el certificado.

Normalmente se almacena 1 certificado en 1 fichero, aunque dependiendo del servidor o software que lo procese podemos encontrarnos con más de 1 certificado en un solo fichero.

Al ser un fichero en formato ASCII en base64 podemos abrir el certificado con un editor de textos, pudiendo ver las cabeceras que determinan los límites del certificado. Todos los certificados en formato PEM tendrán las siguientes cabeceras de comienzo y fin:

-----BEGIN CERTIFICATE-----

Certificado en formato ASCII codificado en Base 64

-----END CERTIFICATE-----

La extensión de estos ficheros suele ser *.pem.

Certificado en formato PKCS#7

Este formato esta soportado por la keytool de la jsdk.

Se utiliza para almacenar el certificado y la cadena completa de certificados intermedios.

Este tipo de formato lo encontraremos en software utilizado para encriptar y firmar datos según la RFC 2315.

La extensión de estos ficheros suele ser *.p7b o *.p7c.

Certificado y clave en formato PKCS#12 o PFX

Se utiliza para almacenar la clave privada junto con la cadena completa de certificados intermedios.

A pesar de que PFX es un formato diferente al PKCS#12, en la actualidad todavía podemos encontrarnos su utilización como sinónimo de PKCS#12.

La extensión de estos ficheros suele ser *.p12 o *.pfx.