¿Cómo extraer la CA raíz y la CA subordinada de una cadena de certificados en Linux?

¿Cómo extraer la CA raíz y la CA subordinada de una cadena de certificados en Linux?

Tengo un certificado de entidad final/servidor que tiene un certificado intermedio y raíz. Cuando accedo catal certificado de entidad final, solo veo una etiqueta BEGINy END. Es el único certificado de entidad final.

¿Hay alguna manera de poder ver el contenido del certificado raíz e intermedio? Sólo necesito el contenido BEGINy ENDla etiqueta.

En Windows puedo ver la cadena de certificados completa en la "Ruta de certificación". A continuación se muestra el ejemplo del certificado de Stack Exchange.

ingrese la descripción de la imagen aquí

Desde allí puedo realizar unVer Certificadoy exportarlos. Puedo hacer eso tanto para el root como para el intermedio en Windows. Estoy buscando este mismo método en Linux.

ingrese la descripción de la imagen aquí

Respuesta1

Desde un sitio web, puedes hacer:

openssl s_client -showcerts -verify 5 -connect stackexchange.com:443 < /dev/null

Eso mostrará la cadena de certificados y todos los certificados que presentó el servidor.

Ahora, si guardo esos dos certificados en archivos, puedo usar openssl verify:

$ openssl verify -show_chain -untrusted dc-sha2.crt se.crt 
se.crt: OK
Chain:
depth=0: C = US, ST = NY, L = New York, O = "Stack Exchange, Inc.", CN = *.stackexchange.com (untrusted)
depth=1: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 High Assurance Server CA (untrusted)
depth=2: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA

La -untrustedopción se utiliza para otorgar el(los) certificado(s) intermedio(s); se.crtes el certificado a verificar. El resultado de profundidad = 2 provino del almacén de CA confiable del sistema.

Si no tiene los certificados intermedios, no podrá realizar la verificación. Así es como funciona X.509.

Dependiendo del certificado, puede contener un URI para obtener el intermedio. A modo de ejemplo, openssl x509 -in se.crt -noout -textcontiene:

        Authority Information Access: 
            OCSP - URI:http://ocsp.digicert.com
            CA Issuers - URI:http://cacerts.digicert.com/DigiCertSHA2HighAssuranceServerCA.crt

Ese URI de "Emisores de CA" apunta al certificado intermedio (en formato DER, por lo que debe usarlo openssl x509 -inform der -in DigiCertSHA2HighAssuranceServerCA.crt -out DigiCertSHA2HighAssuranceServerCA.pempara convertirlo para su uso posterior en OpenSSL).

Si ejecuta, openssl x509 -in /tmp/DigiCertSHA2HighAssuranceServerCA.pem -noout -issuer_hashobtendrá 244b5494, que puede buscar en el almacén de CA raíz del sistema en /etc/ssl/certs/244b5494.0(simplemente agréguelo .0al nombre).

No creo que exista un comando OpenSSL sencillo y agradable que pueda hacer todo eso por usted.

Respuesta2

tl;dr: magia de bash de una sola línea para volcar todos los certificados de la cadena

openssl s_client -showcerts -verify 5 -connect wikipedia.org:443 < /dev/null |
   awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/{ if(/BEGIN CERTIFICATE/){a++}; out="cert"a".pem"; print >out}'
for cert in *.pem; do 
        newname=$(openssl x509 -noout -subject -in $cert | sed -nE 's/.*CN ?= ?(.*)/\1/; s/[ ,.*]/_/g; s/__/_/g; s/_-_/-/; s/^_//g;p' | tr '[:upper:]' '[:lower:]').pem
        echo "${newname}"; mv "${cert}" "${newname}" 
done

Explicación en 2 pasos

Para volcar todos los certificados de la cadena al directorio actual como cert${chain_number}.pem:

openssl s_client -showcerts -verify 5 -connect your_host:443 < /dev/null |
 awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/{ if(/BEGIN CERTIFICATE/){a++}; out="cert"a".pem"; print >out}' 

El bonus-track para cambiarles el nombre a su nombre común:

for cert in *.pem; do 
   newname=$(openssl x509 -noout -subject -in $cert | sed -nE 's/.*CN ?= ?(.*)/\1/; s/[ ,.*]/_/g; s/__/_/g; s/_-_/-/; s/^_//g;p' | tr '[:upper:]' '[:lower:]').pem
   mv $cert $newname 
done

Respuesta3

Descubrí que con la opción -verify 5openssl se profundiza en la cadena mostrando todos los certificados, incluso los que no están incluidos en la implementación de su certificado.

Si realmente desea comprender qué cadena se proporciona con su certificado, debe ejecutar:

openssl s_client -showcerts -partial_chain -connect YOUR_ENDPOINT:443 < /dev/null |less

Respuesta4

Lo anterior no funcionó para mí cuando estaba usando un certificado comodín gratuito de Lets Encrypt.

Para ser más específico:
tengo un clúster de Kubernetes + controlador de ingreso que está configurado usando un certificado comodín gratuito de Lets Encrypt para *.mydomain.dev, aloja los siguientes 2 nombres de dominio:

  • grafana.midominio.dev
  • prometheus.midominio.dev

Tuve que agregar el indicador -servername siguiente en este sitio:https://community.letsencrypt.org/t/where-can-i-download-the-trusted-root-ca-certificates-for-lets-encrypt/33241/2

export DOMAIN=grafana.mydomain.dev
openssl s_client -showcerts -verify 5 -connect $DOMAIN:443 -servername $DOMAIN < /dev/null 2> /dev/null | awk '/BEGIN/,/END/{ if(/BEGIN/){a++}; print}'

También modifiqué la cadena para que me proporcione el certificado completo + intermedio + raíz a la salida estándar y oculte el ruido estándar.

En realidad... Al realizar las pruebas descubrí que esto no me da la CA... openssl s_client -showcerts -verify 5 -connect letsencrypt.org:443 < /dev/null 2> /dev/null | awk '/BEGIN/,/END/{ if(/BEGIN/){a++}; print}'

curl https://letsencrypt.org/certs/isrgrootx1.pem Da un valor diferente (y cuando se prueban algunas cosas, este es el valor que funciona).

información relacionada