Verifique una cadena de certificados usando openssl verificar

128

Estoy construyendo una propia cadena de certificados con los siguientes componentes:

Root Certificate - Intermediate Certificate - User Certificate

Root Cert es un certificado autofirmado, el Certificado Intermedio está firmado por Root y el Usuario por Intermedio.

Ahora quiero verificar si un Certificado de usuario tiene su anclaje mediante 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

error 20 at 0 depth lookup:unable to get local issuer certificate

¿Qué está mal?

Indra
fuente

Respuestas:

164

De la verifydocumentación:

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 autofirmarse para que la verificación funcione. Es por eso que su segundo comando no funcionó. Intenta esto en su lugar:

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

Verificará toda su cadena en un solo comando.

Priyadi
fuente
2
Estoy votando esta respuesta porque recientemente tuve que hacer esto y después de probar diferentes opciones enumeradas por man verify, encontré que el -untrustedparámetro es el correcto para usar al especificar el certificado intermedio.
Anthony Geoghegan
Creo que la segunda respuesta: stackoverflow.com/a/31205833/173062 es más precisa: pasa la cadena de certificados al parámetro -CAfile.
Glenjamin
2
-untrustedno comprueba si la cadena de certificados es totalmente válida. Considere pasar tanto el comando intermedio como el root al comando como -CAfilelo sugieren otras preguntas.
Envek
2
Use -contrusted para Intermediate.pem si es posible que ocurra lo siguiente: mail.python.org/pipermail/cryptography-dev/2016-August/…
Greg Smethells
2
Eso no es lo que solicitó OP, pero en caso de que desee verificar NO una cadena autofirmada, use el archivo CA del sistema / navegador en lugar del suyo. Por ejemplo, en OS X con openssl del uso de homebrew:openssl verify -CAfile /usr/local/etc/openssl/cert.pem -untrusted Intermediate.pem UserCert.pem
Greg Dubicki
50

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

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

Actualizar:

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

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

Desafortunadamente, un certificado "intermedio" que en realidad es una raíz / autofirmado será tratado como una CA confiable cuando se utiliza el comando recomendado anteriormente:

$ openssl verificar -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 no se considera RootCert.pem. Así que asegúrese de que Intermediate.pem provenga de una fuente confiable antes de confiar en el comando anterior.

Peter
fuente
¿Verificará esto realmente el certificado intermedio contra el certificado raíz?
augurar
Lo hace. Acabo de volver a ejecutar los comandos con una cadena que sé que es correcta (sirve el tráfico de producción para mi empleador), y luego nuevamente con otro certificado raíz no relacionado. Ver la transcripción general .
Peter
8
ADVERTENCIA: NO lo use si Intermediate.pem no es confiable. Para obtener más información, lea aquí: mail.python.org/pipermail/cryptography-dev/2016-August/…
Greg Smethells
1
Gracias por señalar eso, Greg. Cuando di la respuesta, descargué las raíces y los intermedios de las páginas de inicio de los emisores, por lo que no se me ocurrió la idea. He actualizado la respuesta para dejar en claro que el intermedio es de confianza implícita con este comando.
Peter
1
@somenickname, vea el comentario de Tony. La opción no confiable es preferible de todos modos. Le sugiero que haga su propia pregunta si desea más ayuda. Los comentarios no son el lugar adecuado para depurar su problema.
Peter
17

El problema es que eso openssl -verifyno hace el trabajo.

Como mencionó Priyadi , se openssl -verifydetiene en el primer certificado autofirmado, por lo tanto, realmente no verifica la cadena, ya que a menudo el certificado intermedio está autofirmado.

Supongo que desea estar 101% seguro, que los archivos de certificado son correctos antes de intentar instalarlos en el productivo servicio web. Esta receta aquí realiza exactamente esta verificación previa al vuelo.

Tenga en cuenta que la respuesta de Peter es correcta , sin embargo, la salida de openssl -verifyno es una pista de que todo realmente funcione después. Sí, puede encontrar algunos problemas, pero no todos.

Aquí hay un script que hace el trabajo para verificar una cadena de certificados antes de instalarlo en Apache. Quizás esto se pueda mejorar con algunas de las magias más místicas de OpenSSL, 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 posterior EVERYTHING OKes la configuración de Apache, porque las personas que usan NginXo haproxygeneralmente 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 raíz de CA de confianza /etc/ssl/certscomo de costumbre, por ejemplo, en Ubuntu
  • Cree un directorio DIRdonde 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.bundleque contiene el paquete CA. Sobre cómo preparar el paquete, ver abajo.
  • Ahora ejecute el script: ./check DIR/certificate(esto supone que el script se nombra checken el directorio actual)
  • Hay un caso muy poco probable de que salga el script CA-Bundle is not needed. Esto significa que usted (léase /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 utilizarse en su estación de trabajo. Y mejor solo ejecute esto en un entorno seguro, ya que abre el puerto 4433 en breve al público, que podría ver conexiones externas en un entorno hostil.

¿Cómo crear el certificate.bundlearchivo?

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 cruzado 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 su certificado, luego se necesita el certificado intermedio desconocido, luego quizás el certificado de firma cruzada y luego /etc/ssl/certsse consulta para encontrar el certificado de confianza adecuado.

El paquete ca debe estar formado exactamente en el orden de procesamiento correcto, esto significa que el primer certificado necesario (el certificado intermedio que firma su certificado) viene primero en el paquete. Entonces se necesita el certificado de firma cruzada.

Por lo general, su CA (la autoridad que firmó su certificado) ya le proporcionará un archivo ca-bundle tan apropiado. De lo contrario, debe elegir todos los certificados intermedios necesarios y catjuntarlos en un solo archivo (en Unix). En Windows, solo puede abrir un editor de texto (como notepad.exe) y pegar los certificados en el archivo, el primero necesario en la parte superior y siguiendo a los demás.

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

Ejemplo:

Tienes:

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

Entonces lo correcto catse vería así:

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

¿Y cómo puede averiguar qué archivos se necesitan o no y en qué secuencia?

Bueno, experimenta, hasta que checkte diga que todo está bien. Es como un juego de rompecabezas de computadora para resolver el enigma. Cada. Soltero. Hora. Incluso para profesionales. Pero mejorará cada vez que necesite hacer esto. Así que 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é la criptografía no se ha convertido en la corriente principal en los últimos 30 años? Es por eso. 'Nuff dijo.

Tino
fuente
Para el votante negativo: explique qué hay de malo en mi respuesta. Gracias.
Tino
2
Soy uno de los downvoters. Lo que desencadenó el voto negativo es esto: "¿Y cómo puede averiguar qué archivos se necesitan o no y en qué secuencia? Bueno, experimente, hasta que la verificación le indique que todo está bien". No creo que SSL sea un caso especial. Problemas como este deberían tener una solución determinista.
ychaouche
2
@ychaouche Gracias! Como tú, me gustan las cosas desterministas. La pregunta era: "¿Qué está mal?" Y cómo hacerlo con "openssl verificar". Como estamos en stackoverflow, expliqué eso, seguido de una respuesta programática (por lo tanto determinista) sí / no. Incluso puede usarlo para automatizar las comprobaciones del nuevo paquete antes de instalarlo en producción. Esto responde completamente a la pregunta. Lo que no le gusta es que le dije sobre la frustración de "¿Cómo crear un paquete adecuado?". Como creo que no puede haber una respuesta determinista corta para eso, responder esto sería un tema fuera de contexto en el contexto aquí.
Tino
66
"Como mencionó Priyadi, openssl -verify se detiene en el primer certificado autofirmado, por lo tanto, no se verifica realmente la cadena, ya que a menudo el certificado intermedio está autofirmado". Obviamente, los certificados intermedios nunca son autofirmados (si lo fueran, serían certificados raíz). Y todo el punto de verificación es verificar que haya incluido todos los certificados en la cadena hasta un certificado raíz de confianza. Esto es precisamente lo que hace la verificación de openssl. Sin embargo, openssl tiende a ser bastante conservador con sus políticas de confianza ...
Timo
44
"a menudo el certificado intermedio es autofirmado". Esto está mal, y las confusiones de terminología como esta dificultan que los recién llegados entiendan un tema que en realidad es bastante simple cuando se explica de la manera correcta. De RFC 5280: "los certificados [...] de CA se pueden dividir en tres clases: certificados cruzados, certificados auto emitidos y certificados autofirmados. Los certificados cruzados son certificados CA en los cuales el emisor y el sujeto son entidades diferentes . Los certificados cruzados describen una relación de confianza entre las dos AC. [...] ".
Dr. Jan-Philip Gehrcke
8

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

  1. Descargue el certificado raíz y el certificado intermedio de la cadena de confianza letsencrypt .
  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
    
Miguel
fuente
1
Bueno, parece que a John no le gustó que dije gracias. Insisto en el "Gracias" difícil, así que aquí está el texto eliminado: Espero que te ayude con tus certificados de letencrypt. Gracias por Priyadi, su solución me ayudó a encontrar este comando. Por favor, asegúrese de votar su solución.
Michael
5

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

Captura de pantalla :

ingrese la descripción de la imagen aquí

praveen.chandran
fuente
1
No intenta responder la pregunta sobre cómo usarla openssl verify.
binki
sí, pero este tipo de herramienta puede proporcionarle la visualización necesaria de ese tipo de cosas si no comprende la información críptica de las herramientas de línea de comandos de openssl :) Así que aquí está mi voto positivo, puede haber algunas cosas en línea que también lo hagan.
David 天宇 Wong
2

Si solo desea verificar que el emisor de UserCert.pem es realmente Intermediate.pem haga lo siguiente (el ejemplo usa:) OpenSSL 1.1.1:

openssl verify -no-CAfile -no-CApath -partial_chain -trusted Intermediate.pem UserCert.pem

y obtendrás:

UserCert.pem: OK

o

UserCert.pem: verification failed
Marinos An
fuente
¿hay algún comando equivalente para openssl verify -no-CAfile -no-CApath -partial_chain -trusted Intermediate.pem UserCert.pemen Python 3.7?
Bogotá
-5

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

openssl x509 -in fullchain.pem -text -noout

jorfus
fuente
44
1) Esto es completamente sin ningún tipo de explicación. 2) esta es una respuesta a una pregunta que el autor de la pregunta no hizo, sin ningún contexto.
Shadur