User Tools

Site Tools


comandos_openssl_utiles_para_certificados

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:

comandos_openssl_utiles_para_certificados.txt · Last modified: 2023/07/12 15:38 by busindre