fingerprint de certificados ssh

Con el tiempo uno va coleccionando muchos certificados, algunos dedicados a un determinado proyecto, otros dedicados a algun cliente y, por supuesto los propios. En ese repositorio de certificados que suele ser la carpeta ~/.ssh/ hay que agregar los certificados que por algun motivo distribuimos en algunos servidores… en fin, llegará el día que necesitemos identificar algun certificado privado.

Así que estos son los comandos para obtener el fingerprint (huella dactilar) de certificados privados.

Certificado ssh

$ openssl rsa -in id_rsa -pubout -outform DER | openssl md5 -c
Enter pass phrase for .ssh/id_rsa:
writing RSA key
a2:d7:19:27:fa:89:43:aa:59:fd:ac:eb:71:3f:fb:a8

Como ven, mi certificado privado tiene passphrase y, para leerlo se require que la escriba.

Certificado pem (AWS)

openssl pkcs8 -in .ssh/proyectoX  -inform PEM -outform DER -topk8 -nocrypt | openssl sha1 -c
d3:ff:c0:cf:6f:25:a1:88:b5:c7:9e:9b:ba:b9:57:a4:bb:45:62:68

Los certificados que creamos en AWS se suelen guardar sin passphrase y el fingerprint se muestra inmediatamente.

Verificando certificados SSL desde la línea de comandos

Recientemente he necesitado revisar el vencimiento de certificados SSL mediante un script que me permitiera conocer el estado de los mismos en muchos servidores.

Una primer opción era ejecutar el comando openssl para verificar cada certificado:

$ openssl x509 -in certificado.pem -noout -enddate
notAfter=Oct 24 23:59:59 2014 GMT

y automatizarlo mediante conexiones ssh, pero el problema es que los certificados no tienen todos el mismo nombre, ni están instalados en el mismo directorio, pues algunos fueron instalados dependiendo del servicio.

Así que la opción fue utilizar openssl para abrir conexiones como cliente y verificar qué vencimiento tiene el certificado del servicio correspondiente:

$ echo | openssl s_client -connect servidor.com:443 2>/dev/null | openssl x509 -noout -dates
notBefore=Oct 24 00:00:00 2013 GMT
notAfter=Oct 24 23:59:59 2014 GMT

El echo inicial envía un enter al comando openssl para que el cliente no conectado y de esta forma con un listado de nombres de servidor y los puertos, se puede revisar toda una infraestructura de servidores y servicios.

Algunas argumentos que pueden ser pasados a openssl para obtener datos de certificados X509:

  • –dates fechas del período de validez del certificado
  • –enddate fecha de vencimiento
  • –subject titular del certificado y CN
  • –issuer autoridad de certificación
  • –fingerprint huella dactilar del certificado
  • –text toda la información del certificado

Estos comandos pueden ser utilizados en conjunto para obtener más de una información en la misma consulta:

$ echo | openssl s_client -connect servidor.com:443 2>/dev/null | openssl x509 -noout -dates -issuer -fingerprint
notBefore=Oct 24 00:00:00 2013 GMT
notAfter=Oct 24 23:59:59 2014 GMT
issuer= /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=EssentialSSL CA
SHA1 Fingerprint=6F:24:52:8F:10:E0:6D:AB:C9:BB:1D:52:65:F6:A8:47:89:BE:A3:5F

y quitando el -noout se obtiene el certificado:

$ echo | openssl s_client -connect servidor.com:443 2>/dev/null | openssl x509
-----BEGIN CERTIFICATE-----
MIIFIjCCBAqgAwIBAgIQMK1wptvY36IzHyscziufKTANBgkqhkiG9w0BAQUFADBy
MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD
...
nZpAVhzwHIS5wzMMHc5XRFvv3Ohnsco1CAA76HBBrMjmC6OYFXVDX+LgXjnTvuS8
lpg865wT5NUeWtWoRCOQydIHXqatpEyysbBZ/QbUA9CjjWViowRfYub2jZJ3v1k4
SsEYTJTsv3duHmn5Zn+dhINdVgVEJA==
-----END CERTIFICATE-----

y, por supuesto, para la consulta de un solo certificado, a veces es útil alguna herramienta web como esta de SSLShopper

Con curl


$ curl -s --insecure -v https://servidor.com \
| awk 'BEGIN { cert=0 } /^\* Server certificate:/ \
{ cert=1 } /^\*/ { if (cert) print }'

* Rebuilt URL to: https://servidor.com/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 13.249.87.93...
* TCP_NODELAY set
* Connected to servidor.com (x.x.x.x) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
} [5 bytes data]
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.2 (IN), TLS handshake, Server hello (2):
{ [76 bytes data]

...

* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: CN=servidor.com
* start date: Aug 16 00:00:00 2019 GMT
* expire date: Sep 16 12:00:00 2020 GMT
* issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
* SSL certificate verify ok.
} [5 bytes data]
> GET / HTTP/1.1
> Host: servidor.com
> User-Agent: curl/7.52.1
> Accept: */*
>