Table of Contents
Comandos OpenSSL para trabajar con certificados digitales evitando SHA1
Los ejemplos utilizan algoritmo de firma SHA-512, el más fuerte de la familia SHA-2 a fecha de este artículo. Por defecto OpenSSL utiliza SHA1, el cual es considerado inseguro y debe evitarse como algoritmo de firma en certificados digitales. Leer.
NOTA: Passphrase = Contraseña = Clave.
Signature Algorithm: sha512WithRSAEncryption
RSA vs EC
Se recomienda el uso de EC en vez de RSA cuando sea posible.
# Listar las curvas disponibles openssl ecparam -list_curves # Generación de una llave privada EC. openssl ecparam -name prime256v1 -genkey -noout -out private-key.pem # Generación de una llave privada EC cifrada (Pidiendo el password por el promt y algoritmo de cifrado AES256). openssl genpkey -out private-key.pem -outform PEM -aes256 -algorithm ec -pkeyopt ec_paramgen_curve:prime256v1 # Generación de una llave privada EC cifrada (Indicando como parámetro la password XXXXX y algoritmo de cifrado AES256). openssl genpkey -out private-key.pem -outform PEM -pass pass:XXXXX -aes256 -algorithm ec -pkeyopt ec_paramgen_curve:prime256v1 # Generación de una llave pública EC. openssl ec -in private-key.pem -pubout -out public-key.pem
Casi todos los comandos funcionan tanto con llaves RSA como con llaves EC, simplemente hay que estar atento a los parámetros en uso.
# RSA -newkey rsa:4096 # EC -newkey ec -pkeyopt ec_paramgen_curve:sect571r1
Comandos generales (Generar CSRs, Certificados, llaves privadas, etc).
Generar llave privada + Certificate Signing Request.
# RSA openssl req -sha512 -out CSR.csr -new -newkey rsa:4096 -nodes -keyout privateKey.key # EC (Consultar qué tipo de curva se va a suar mediante openssl ecparam -list_curves) openssl req -sha512 -out CSR.csr -new -newkey ec -pkeyopt ec_paramgen_curve:sect571r1 -nodes -keyout privateKey.key
Generar certificado autofirmado. (SHA-512 / RSA 4096).
# RSA openssl req -x509 -nodes -sha512 -days 365 -newkey rsa:4096 -keyout privateKey.key -out certificate.crt # EC openssl req -x509 -nodes -sha512 -days 365 -newkey ec -pkeyopt ec_paramgen_curve:sect571r1 -keyout privateKey.key -out certificate.crt
Generar certificado autofirmado a partir de una llave privada existente. (SHA-512)
openssl req -key privateKey.key -new -x509 -nodes -sha512 -days 365 -out certificate.crt
Generar una solicitud de certificado csr (Certificate Signing Request) a partir de una llave privada.
openssl req -sha512 -out CSR.csr -key privateKey.key -new
Generar una solicitud de certificado csr (Certificate Signing Request) a partir de un certificado existente.
openssl x509 -sha512 -x509toreq -x509toreq -copy_extensions -in certificate.crt -out CSR.csr -signkey privateKey.key
Generar certificado autofirmado con SAN. (SHA-512 / RSA 4096 o EC).
# Para crear un certificado para múltiples dominios, es decir, no solo basado en CN, debe crearse un fichero CSR primeramente con la información pertinente. ### Fichero req.cnf [req] distinguished_name = req_distinguished_name x509_extensions = v3_req prompt = no [req_distinguished_name] C = ES ST = Bayern L = Munich O = Inventos OU = IT CN = www.dominio.com [v3_req] keyUsage = keyEncipherment, dataEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] DNS.1 = www.dominio.com DNS.2 = www2.dominio.com DNS.3 = portainer.dominio.com DNS.4 = traefik.cominio.com ### Generar el certificado autofirmado basado en la configuración anterior definida en req.cnf. # RSA openssl req -x509 -nodes -sha512 -days 365 -newkey rsa:4096 -keyout privateKey.key -out certificate.crt -config req.cnf -extensions 'v3_req' # EC (Depende del cliente / navegador que conecte con el certificado, la curva debe elegirse acorde a la compatibilidad, actualmente 2021 muy pocas están soportadas por los navegadores) openssl req -x509 -nodes -sha512 -days 365 -newkey ec -pkeyopt ec_paramgen_curve:sect571r1 -keyout privateKey.key -out certificate.crt -config req.cnf -extensions 'v3_req' # Mensaje de Curl al acceder a un certificado https que usa EC. # curl: (35) error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
Eliminar contraseña (passphrase) de cifrado de una llave privada openssl. (Si se usa el mismo nombre se sobreescribe).
# RSA openssl rsa -in privateKey.pem -out newPrivateKey.pem # ECC openssl ec -in privateKey.pem -out newPrivateKey.pem
Cifrar llave privada con contraseña (passphrase). (Si se usa el mismo nombre se sobreescribe).
# RSA openssl rsa -des -in privateKey_sin_pwd.key -out privateKey_con_pwd.key # EC openssl ec -des -in privateKey_sin_pwd.key -out privateKey_con_pwd.key
Cambiar clave de cifrado de una llave privada (Si se usa el mismo nombre de fichero salida se sobrescribe).
openssl rsa -des -in privateKey.key -out privateKey_new_pwd.key
Revisar Certificados y CSRs (locales o remotos)
Con Openssl es posible conectar a servidores remotos y obtener información sobre los certificados usados. Para ello se usa la opción “-connect”, pero debemos tener en cuenta el protocolo usado por el puerto. Dependiendo del tipo de protocolo usado, será necesario incluir la opción “-starttls protocolo”. Esto se debe a a que muchos servicios ofrecen cifrado, pero únicamente si este es solicitado de manera explicita (por ejemplo en SMTP mediante STARTTLS). En casos como SMTP (NO SMTPS !!) o XMPP sería obligatorio el uso de ese parámetro, pero no así en otros como HTTPS o SMTPS. Más adelante se ven ejemplos relacionados con este concepto.
Revisar / Mostrar información de una solicitud de firma de certificado CSR (Certificate Signing Request).
openssl req -text -noout -verify -in CSR.csr
Revisar / Mostrar información de una llave privada.
# RSA openssl rsa -in privateKey.key -check # EC openssl ec -in privateKey.key -check
Revisar / Mostrar información de un certificado X509 en formatos: PEM / DER / NET.
# Formato PEM por defecto # openssl x509 -in tsa.crt -text -noout openssl x509 -inform PEM -in certificado.crt -text -noout openssl x509 -inform DER -in certificado.crt -text -noout openssl x509 -inform NET -in certificado.crt -text -noout
Revisar / Mostrar información de un certificado PKCS#12 (Extensiones: .pfx o .p12).
openssl pkcs12 -info -in keyStore.p12
Mostrar información de un certificado usando como salida la estructura ASN.1.
openssl asn1parse -in certificado.pem # PEM openssl asn1parse -inform DER -in certificado.der # DER
Extraer llave privada y certificado de un certificado / contenedor PKCS#12
openssl pkcs12 -in keyStore.p12 -nocerts -out key.pem openssl pkcs12 -in keyStore.p12 -clcerts -nokeys -out certificado.pem
Herramienta para fuerza bruta contra certificados PKCS#12: http://crackpkcs12.sourceforge.net
Extraer llave pública de un certificado.
openssl x509 -pubkey -noout -in certificado.crt > certificado_publey.crt
Extraer el hash (ej. sha256) de una llave contenido en un certificado (key modulus).
openssl x509 -noout -modulus -in cacert.pem | openssl sha256 openssl x509 -noout -modulus -in cacert.pem | sha256sum # Mismo resultado que el anterior.
Revisar fechas de un certificado remoto (HTTPS / XMPP / SMTP over TLS).
# HTTPS. echo | openssl s_client -connect www.busindre.com:443 2>/dev/null |openssl x509 -dates -noout # XMPP (-starttls xmpp). echo | openssl s_client -connect busindre.com:5222 -starttls xmpp 2>/dev/null |openssl x509 -dates -noout # SMTP over TLS(-starttls smtp). echo | openssl s_client -connect mxext3.mailbox.org:25 -starttls smtp 2>/dev/null |openssl x509 -dates -noout # SMTPS (No necesita de starttls ya que es un puerto pensado para el uso cifrado únicamente). echo | openssl s_client -connect smtp.gmail.com:465 2>/dev/null |openssl x509 -dates -noout
Revisar si se utiliza un certificado con cifrado “débil”.
openssl s_client -connect www.busindre.com:443 -cipher LOW
Descargar un certificado / cadena de certificados de un servidor web.
# Certificado HTTPS. openssl s_client -connect busindre.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > /tmp/busindre.com.cert # Cadena de certificados (certificate chain) de un servidor HTTPS. openssl s_client -connect busindre.com:443 -showcerts 2>&1 < /dev/null
Obtener la URL al OCSP URI.
openssl x509 -noout -ocsp_uri -in /tmp/busindre.com.cert
Revisar certificados revocados de una lista CRL
openssl crl -in root_ca.crl -noout -text
Revisar certificados revocados mediante OCSP
openssl ocsp -sha512 -CAfile cacert.pem -issuer cacert.pem -cert server.crt -url http://XXX:2560 -resp_text
Comprobar que un certificado firmado corresponde a una CA en concreto.
openssl verify -verbose -CAfile cacert.pem server.crt
Revisar cifrados habilitados en un determinado servidor SSL
Para saber qué algoritmos de cifrado están disponibles en un determinado servicio SSL se pueden utilizar las siguientes herramientas.
Usando “nmap” para saber qué cifrados están soportados para cada protocolo (SSLv3,TLS,..). Método recomendado.
nmap --script ssl-enum-ciphers -p 443 domain.com
Script en bash. Lista los cifrados de la versión de OpenSSL instalada y comprueba los mismos sobre el host.
#!/usr/bin/env bash # OpenSSL requires the port number. SERVER=dominio.com:443 DELAY=1 #ciphers=$(openssl ciphers 'TLSv1' | sed -e 's/:/ /g') # Solo cifrados de TLSv1. ciphers=$(openssl ciphers | sed -e 's/:/ /g') # Todos los cifrados de OpenSSL. echo Obtaining cipher list from $(openssl version). for cipher in ${ciphers[@]} do echo -n Testing $cipher... result=$(echo -n | openssl s_client -cipher "$cipher" -connect $SERVER 2>&1) if [[ "$result" =~ "Cipher is ${cipher}" || "$result" =~ "Cipher :" ]] ; then echo YES else if [[ "$result" =~ ":error:" ]] ; then error=$(echo -n $result | cut -d':' -f6) echo NO \($error\) else echo UNKNOWN RESPONSE echo $result fi fi sleep $DELAY done
Forzar a Firefox para que utilice una versión concreta de TLS / SSL.
Firefox > about:config
security.tls.version.min
- 0 = SSL 3.0 okay
- 1 = at least TLS 1.0
- 2 = at least TLS 1.1
security.tls.version.max
- 0 = up to SSL 3.0
- 1 = up to TLS 1.0
- 2 = up to TLS 1.1
Curl. Ejemplo usando la version SSLv2.
curl -L -k -2 https://dominio.com
Comandos de debug de OpenSSL.
Comprobar si un certificado o solicitud de certificado se corresponde con una determinada llave privada (RSA).
openssl x509 -noout -modulus -in certificate.crt | openssl md5 openssl rsa -noout -modulus -in privateKey.key | openssl md5 openssl req -noout -modulus -in CSR.csr | openssl md5
NOTA: Se puede cambiar md5 por sha1.
Revisa una conexión SSL, se muestran todos los certificados, incluidos los intermedios.
openssl s_client -connect www.busindre.com:443
Conversiones de formato en OpenSSL
Convertir certificados DER (.crt .cer .der) al estandar PEM y viceversa.
openssl x509 -inform der -in certificate.cer -out certificate.pem openssl x509 -outform der -in certificate.pem -out certificate.der
Convertir llaves DER (.crt .cer .der) al estandar PEM y viceversa.
# RSA openssl rsa -inform der -in certificate.cer -out certificate.pem openssl rsa -outform der -in certificate.pem -out certificate.der # EC PEM to DER openssl ec -in certificate.der -inform DER -outform PEM -out certificate.pem openssl ec -in certificate.pem -inform PEM -outform DER -out certificate.der
Convertir ficheros PKCS#12 (.pfx .p12) con llave privada y certificado a PEM.
openssl pkcs12 -in keyStore.pfx -out keyStore.pem -nodes
Se puede utilizar “-nocerts” para obtener solo la llave privada o “-nokeys” para obtener solo el certificado.
Convertir certificado PEM y una llave privada a formato PKCS#12 (.pfx .p12) y viceversa.
openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CACert.crt # AVISO: El fichero PEM resultante contendrá también la llave privada y cualquier otro certificado contenido en el original pkcs12 (certificado público, raíz, intermedio, etc). openssl pkcs12 -in domain.pfx -nodes -out domain.combined.crt
NOTA: El formato PKCS12 no soporta SHA512 como algoritmo de firma (leer).
Convertir certificado PEM a PKCS7 y viceversa.
openssl crl2pkcs7 -nocrl -certfile certificate.crt -certfile ca-chain.crt -out certificate.p7b openssl pkcs7 -in certificate.p7b -print_certs -out certificate.crt
Obtener Fingerprint / Thumbprint de certificados.
El Fingerprint / Thumbprint es un identificador utilizado por algunas plataformas de servidor para ubicar el certificado en un almacén de certificados.
# SHA512 openssl x509 -noout -fingerprint -sha512 -inform pem -in file.crt # SHA-256 openssl x509 -noout -fingerprint -sha256 -inform pem -in file.crt # SHA-1 openssl x509 -noout -fingerprint -sha1 -inform pem -in file.crt # MD5 openssl x509 -noout -fingerprint -md5 -inform pem -in file.crt
Certificate Pinning / Public Key Pinning / HTTP Public-Key-Pinning (HPKP).
A grandes rasgos el “certificate pinning” se basa en que los navegadores guardan una huella digital (SPKI fingerprint) de la clave pública usada por un servidor HTTPS. Si alguien consiguiera vulnerar la CA que ha firmado dicho certificado y pudiera, a su vez, emitir certificados válidos para realizar ataques MIM, el “certificate pinning” sería el encargado de protegernos.
Cuando el atacante pone el certificado fraudulento (pero válido) para realizar el ataque de MIM, el navegador hará “pinning”, comprobando que la huella digital del servidor coincide con la guardada en el navegador, como en este caso, la clave pública del certificado no puede tener el mismo fingerprint que el servidor auténtico, el usuario será avisado del problema o simplemente denegará la conectividad. Si el servidor web no implementara dicha medida de seguridad, la conexión HTTPS sería a ojos del navegador 100% legítima.
La única manera de que alguien pudiera suplantar ese “SPKI fingerprint”, es hacerse con la llave privada del servidor HTTPS. Por ello siempre es recomendable tener en otro lugar otro juego de llaves como backup, cuya huella debe ser también especificada en la configuración del servidor HTTPS. Es decir, en el servidor HTTPS se deben especificar siempre dos “SPKI fingerprints”, de esta manera, si la llave privada en producción es vulnerada, siempre se puede generar otro certificado con el juego de claves de backups y así los usuarios con la huella todavía guardada pueden seguir visitando la web. Mientras una de las dos huellas (producción / backup) funcionen, el navegador no pondrá pega ninguna.
Ejemplo de cabecera HPKP.
Public-Key-Pins: pin-sha256="cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs="; pin-sha256="M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE="; max-age=5184000; includeSubdomains; report-uri="https://www.example.net/hpkp-report"
Obtener el “SPKI fingerprint” (Base64) a partir de una clave privada.
# RSA openssl rsa -in file.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64 # EC openssl ec -in file.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64
Obtener el “SPKI fingerprint” (Base64) a partir de un csr (certificate signing request).
openssl req -in file.csr -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
Obtener el “SPKI fingerprint” (Base64) a partir de un certificado.
# RSA openssl x509 -in file.crt -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64 # EC openssl x509 -in file.crt -pubkey -noout | openssl ec -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
Obtener el “SPKI fingerprint” (Base64) de un servidor HTTPS.
# RSA openssl s_client -servername www.busindre.com -connect www.busindre.com:443 | openssl x509 -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64 # EC openssl s_client -servername www.busindre.com -connect www.busindre.com:443 | openssl x509 -pubkey -noout | openssl ec -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
Crear CSR / Firmar CSR multidominio (SAN): crear_y_firmar_csrs_multidominio_san
Campos de certificados X.509
Version: Especifica la versión del protocolo X.509 con la que se ha construido el certificado, por ejemplo, si el certificado contuviera extensiones este campo debería contener inequívocamente el valor ‘3’.
Serial Number (Número de Serie): Se trata de un número entero positivo que puede asignar la CA y que le permitirá identificar el certificado digital. Por lo tanto este identificador deberá ser único para cada certificado dentro de una cadena de confianza. Lo habitual es que se trate de números de módulo largo, lo que asciende a 20 octetos.
Signature Algorithm Identifier (Identificador del Algoritmo de Firma): Este campo contiene necesariamente el algoritmo de cifrado empleado para generar la firma del suscriptor. Debe ser necesariamente el mismo que el que se emplea en la firma de validación de la cadena de confianza. Adicionalmente se consideran extensiones opcionales para este campo, que dependerán directamente del algoritmo de cifrado empleado.
Issuer (Emisor): Este campo contiene información respecto a la Autoridad de Certificación que ha emitido el certificado digital, fundamentalmente del certificado de CA subordinada que se ha empleado para generar el certificado final. Concretamente cuenta con estos campos (para facilitar la legibilidad de la entrada nos centramos en los de mayor importancia y de uso más extendido):
country: País donde su ubica la CA.
organization: Nombre establecido para la CA.
organizational unit: Campo definido para la unidad organizativa del certificado, se suele definir con un identificador de la finalidad del certificado o el departamento encargado de generarlo.
state or province name: Nombre de estado o provincia, dependiendo de la organización del país en el que se ubica la CA.
common name (CN): Se define como nombre común, y se define normalmente como el common name del subject del certificado de subordinada que se ha empleado para firmar el certificado.
Locality: Ciudad donde se ubica la CA.
NOTA: Los campos title, surname, given name, initials, pseudonym o generation qualifier, se definen también para el campo de emisor, aunque no se suelen emplear cuando quien emite el certificado es una CA (como podéis ver carecen de sentido para una entidad jurídica).
Validity: Se trata de un campo fundamental dentro del mecanismo de uso de una PKI. Es el tiempo que se compromete la Autoridad de Certificación a disponer de información sobre la validez del certificado, lo que se traduce en consecuencia que este campo establece la vida útil del certificado. Se puede codificar empleando dos mecanismos UTCTime y GeneralizedTime.
Subject (Suscriptor): Campo que incluye los datos del suscriptor (o usuario final) del certificado, por lo que va directamente asociado a la clave pública contenida en el mismo certificado. Del mismo modo que en el caso anterior, nos centramos en los campos fundamentales y de uso más extendido, habiendo una especificación muy extensa de posibles campos para este punto:
Common name: Nombre asignado al certificado en concreto, depende mucho del tipo de certificado que se trate, por ejemplo en un certificado SSL lo habitual es incluir el nombre del dominio que emplea el certificado, en caso de certificados de firma suele emplearse el nombre completo de la persona.
Serial number: Número de serie identificativo que se emplea para identificar inequívocamente un certificado emitido, este número debe ser único para cada certificado dentro de una CA.
GivenName: Nombre propio de la persona en el caso de certificados personales.
SurName: Apellidos de la persona para certificados personales.
Organization unit: Puede hacer referencia al uso del certificado, o a la finalidad de la rama de la jerarquía de certificación empleada (o CA subordinada).
Organization: Este caso es común al campo Issuer, ya que se suele poner el identificador de la CA emisora.
Country: País de emisión del certificado.
Subject Public Key Info: Campo definido para contener la clave pública del certificado, así como para identificar el algoritmo de cifrado empleado para su generación.
Extensiones de los certificados X.509 (Opcionales)
Authority Key Identifier: Campo que se emplea para identificar inequívocamente a la autoridad de certificación.
Subject Key Identifier: Campo que se emplea para identificar inequívocamente al suscriptor.
Key Usage: Especifica cuales son los usos válidos para el certificado, como por ejemplo si se puede emplear para firmar o para cifrar.
Certificate Policies: Define la ubicación e identificación de la Política de Certificado definida para la subordinada que ha generado el certificado.
Basic Constraints: Incluye información muy importante como si el certificado es de CA, lo que permitiría que el certificado se empleara para firmar otros certificados.
CRL Distribution Points: En esta extensión se detalla la ruta del enlace donde se pueden obtener las Listas de Revocación de Certificados (CRL) correspondientes a la subordinada que emite el certificado final, de este modo se puede automatizar la consulta de las mismas cuando se consulta el certificado.
Authority Information Access: Del mismo modo que en el caso anterior, en esta extensión se mantiene la ruta de acceso al servicio de validación OCSP de la CA, facilitando también la automatización de la validación pudiendo obtener dicha información del propio certificado.
Como depurar una conexión SSL/TLS (gnutls-cli).
La opción -d puede llegar hasta 999 para especificar un nivel de depuración.
echo quit | gnutls-cli -d 10 busindre.com -p 443 echo quit | gnutls-cli smtp.gmail.com -p 465
Enlaces de interés: