Verificar una cadena de certificados usando openssl verificar

Estoy construyendo una cadena de certificados propios con los siguientes componentes:
Root Certificate - Intermediate Certificate - User Certificate
Root Cert es un certificado autofirmado, el Certificado Intermedio está firmado por Root y User por Intermediate.

Ahora quiero verificar si un certificado de usuario tiene su anclaje por certificado raíz.

Con
openssl verify -verbose -CAfile RootCert.pem Intermediate.pem
la validación está bien. En el siguiente paso valido el Certificado de usuario con
openssl verify -verbose -CAfile Intermediate.pem UserCert.pem
y la validación muestra el error 20 en la búsqueda de profundidad 0: no se puede obtener el certificado de emisor local

¿Qué está mal?

De la documentación ‘verificar’: “Si se encuentra un certificado que es su propio emisor, se supone que es la CA raíz”. En otras palabras, la CA raíz debe auto-firmarse para que verify funcione. Es por eso que tu segundo comando no funcionó.

Pruebe esto en su lugar:

 openssl verify -CAfile RootCert.pem -untrusted Intermediate.pem UserCert.pem 

Verificará toda su cadena en un solo comando.

Ese es uno de los pocos trabajos legítimos para cat :

 openssl verify -verbose -CAfile <(cat Intermediate.pem RootCert.pem) UserCert.pem 

Actualizar:

Como señala Greg Smethells en los comentarios, este comando confía implícitamente en Intermediate.pem . Recomiendo leer la primera parte de las referencias de Greg a la publicación (la segunda parte es específicamente sobre pyOpenSSL y no es relevante para esta pregunta).

En caso de que la publicación se vaya, citaré los párrafos importantes:

Desafortunadamente, un certificado "intermedio" que en realidad es una raíz / autofirmado se tratará como una CA confiable cuando se usa el comando recomendado que se indica arriba:

$ openssl verify -CAfile <(cat geotrust_global_ca.pem rogue_ca.pem) fake_sometechcompany_from_rogue_ca.com.pem fake_sometechcompany_from_rogue_ca.com.pem: OK

Parece que openssl dejará de verificar la cadena tan pronto como se encuentre un certificado raíz, que también puede ser Intermediate.pem si está autofirmado. En ese caso, RootCert.pem no se considera. Así que asegúrese de que Intermediate.pem proviene de una fuente confiable antes de confiar en el comando anterior.

El problema es que openssl -verify no hace el trabajo.

Como mencionó Priyadi , openssl -verify detiene en el primer certificado autofirmado, por lo tanto, no se verifica realmente la cadena, ya que a menudo el certificado intermedio se firma por sí mismo.

Supongo que quiere estar 101% seguro de que los archivos del certificado son correctos antes de intentar instalarlos en el servicio web productivo. Esta receta aquí realiza exactamente este control previo al vuelo.

Tenga en cuenta que la respuesta de Peter es correcta , sin embargo, el resultado de openssl -verify no es una pista de que todo funciona realmente después. Sí, podría encontrar algunos problemas, pero no todos.

Aquí hay una secuencia de comandos que hace el trabajo para verificar una cadena de certificados antes de instalarlo en Apache. Tal vez esto se puede mejorar con algunos de los místicos OpenSSL mágicos, pero no soy un gurú de OpenSSL y los siguientes trabajos:

 #!/bin/bash # This Works is placed under the terms of the Copyright Less License, # see file COPYRIGHT.CLL. USE AT OWN RISK, ABSOLUTELY NO WARRANTY. # # COPYRIGHT.CLL can be found at http://permalink.de/tino/cll # (CLL is CC0 as long as not covered by any Copyright) OOPS() { echo "OOPS: $*" >&2; exit 23; } PID= kick() { [ -n "$PID" ] && kill "$PID" && sleep .2; PID=; } trap 'kick' 0 serve() { kick PID= openssl s_server -key "$KEY" -cert "$CRT" "$@" -www & PID=$! sleep .5 # give it time to startup } check() { while read -r line do case "$line" in 'Verify return code: 0 (ok)') return 0;; 'Verify return code: '*) return 1;; # *) echo "::: $line :::";; esac done < <(echo | openssl s_client -verify 8 -CApath /etc/ssl/certs/) OOPS "Something failed, verification output not found!" return 2 } ARG="${1%.}" KEY="$ARG.key" CRT="$ARG.crt" BND="$ARG.bundle" for a in "$KEY" "$CRT" "$BND" do [ -s "$a" ] || OOPS "missing $a" done serve check && echo "!!! =========> CA-Bundle is not needed! <========" echo serve -CAfile "$BND" check ret=$? kick echo case $ret in 0) echo "EVERYTHING OK" echo "SSLCertificateKeyFile $KEY" echo "SSLCertificateFile $CRT" echo "SSLCACertificateFile $BND" ;; *) echo "!!! =========> something is wrong, verification failed! <======== ($ret)";; esac exit $ret 

Tenga en cuenta que la salida después de EVERYTHING OK es la configuración de Apache, porque las personas que usan NginX o haproxy general también pueden leer y comprender esto perfectamente;)

Hay un GitHub Gist de esto que podría tener algunas actualizaciones

Requisitos previos de este script:

  • Tiene los datos de raíz de CA de confianza en /etc/ssl/certs como es habitual, por ejemplo en Ubuntu
  • Cree un directorio DIR donde almacene 3 archivos:
    • DIR/certificate.crt que contiene el certificado
    • DIR/certificate.key que contiene la clave secreta para su servicio web (sin frase de contraseña)
    • DIR/certificate.bundle que contiene el CA-Bundle. Sobre cómo preparar el paquete, ver a continuación.
  • Ahora ejecute el script: ./check DIR/certificate (esto supone que el script se llama check en el directorio actual)
  • Hay un caso muy poco probable de que el script produzca CA-Bundle is not needed . Esto significa que usted (lea: /etc/ssl/certs/ ) ya confía en el certificado de firma. Pero esto es muy poco probable en la WWW.
  • Para esta prueba, el puerto 4433 no debe usarse en su estación de trabajo. Y mejor solo ejecute esto en un entorno seguro, ya que abre el puerto 4433 en breve para el público, que podría ver conexiones extranjeras en un entorno hostil.

¿Cómo crear el archivo certificate.bundle ?

En la WWW, la cadena de confianza generalmente se ve así:

  • Certificado de confianza de /etc/ssl/certs
  • certificado (s) intermedio (s) desconocido (s), posiblemente firmado por otra CA
  • su certificado ( certificate.crt )

Ahora, la evaluación se lleva a cabo de abajo hacia arriba, esto significa que primero se lee el certificado, luego se necesita el certificado intermedio desconocido, luego se consulta el certificado de firma cruzada y /etc/ssl/certs para encontrar el certificado. certificado de confianza apropiado.

El paquete ca se debe componer de la orden de procesamiento correcta, es decir, el primer certificado necesario (el certificado intermedio que firma su certificado) es lo primero en el paquete. Entonces se necesita el certificado de firma cruzada.

Por lo general, su CA (la autoridad que firmó su certificado) ya proporcionará un archivo ca-bundle adecuado. De lo contrario, debe elegir todos los certificados intermedios necesarios y agruparlos en un único archivo (en Unix). En Windows puede simplemente abrir un editor de texto (como notepad.exe ) y pegar los certificados en el archivo, el primero se necesita en la parte superior y sigue los otros.

Hay otra cosa. Los archivos deben estar en formato PEM. Algunas CA emiten formato DER (un binario). PEM es fácil de detectar: ​​es legible por ASCII. Para más información sobre cómo convertir algo en PEM, consulte Cómo convertir .crt a .pem y seguir el camino de ladrillos amarillos.

Ejemplo:

Tienes:

  • intermediate2.crt el certificate.crt intermedio que firmó su certificate.crt
  • intermediate1.crt otro certificado intermedio, que chamusó intermediate2.crt
  • crossigned.crt que es un certificado de firma cruzada de otra CA, que firmó intermediate1.crt
  • crossintermediate.crt que es otro intermedio de la otra CA que firmó crossigned.crt (probablemente nunca verás tal cosa)

Entonces el cat adecuado se vería así:

 cat intermediate2.crt intermediate1.crt crossigned.crt crossintermediate.crt > certificate.bundle 

¿Y cómo puede averiguar qué archivos son necesarios y en qué secuencia?

Bueno, experimenta, hasta que el check te diga que todo está bien. Es como un juego de rompecabezas para resolver el enigma. Cada. Soltero. Hora. Incluso para profesionales. Pero mejorarás cada vez que necesites hacer esto. Entonces definitivamente no estás solo con todo ese dolor. Es SSL, ¿sabes? SSL es probablemente uno de los peores diseños que he visto en más de 30 años de administración profesional de sistemas. ¿Alguna vez se preguntó por qué crypto no se ha convertido en la stream principal en los últimos 30 años? Es por eso. 'dijo nuff.

Después de romper un día entero en el mismo problema, sin conocimiento previo de los certificados SSL, descargué el Administrador de Keystores de CERTivity e importé mi keystore a él, y obtuve una visualización clara de la cadena de certificados.

Captura de pantalla :

enter image description here

Tuve que hacer una verificación de un certificado de letsencrypt y lo hice así:

  1. Descargue el certificado raíz y el certificado intermedio de la cadena de confianza letsencrypt: https://letsencrypt.org/certificates/
  2. emita este comando:

openssl verify -CAfile letsencrypt-root-cert/isrgrootx1.pem.txt -untrusted letsencrypt-intermediate-cert/letsencryptauthorityx3.pem.txt /etc/letsencrypt/live/sitename.tld/cert.pem /etc/letsencrypt/live/sitename.tld/cert.pem: OK

Espero que te ayude con tus certificaciones de letsencrypt. Gracias por Priyadi, tu solución me ayudó a encontrar este comando. Por favor asegúrese de votar su solución.

Puede verificar fácilmente una cadena de certificados con openssl. La cadena completa incluirá el certificado CA, por lo que debería ver detalles sobre la CA y el certificado en sí.

openssl x509 -en fullchain.pem -text -noout