Verifica una catena di certificati usando openssl verifica


128

Sto costruendo una propria catena di certificati con i seguenti componenti:

Root Certificate - Intermediate Certificate - User Certificate

Il certificato radice è un certificato autofirmato, il certificato intermedio è firmato da radice e l'utente da intermedio.

Ora voglio verificare se un certificato utente ha il suo ancoraggio tramite certificato radice.

Con

openssl verify -verbose -CAfile RootCert.pem Intermediate.pem

la validazione è ok. Nel passaggio successivo convalido il certificato utente con

openssl verify -verbose -CAfile Intermediate.pem UserCert.pem

e la convalida mostra

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

Che c'è?

Risposte:


164

Dalla verifydocumentazione:

Se viene trovato un certificato che è il proprio emittente, si presume che sia la CA principale.

In altre parole, la CA principale deve autofirmarsi per verificare che funzioni. Ecco perché il tuo secondo comando non ha funzionato. Prova questo invece:

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

Verificherà l'intera catena in un singolo comando.


2
Sto votando a favore di questa risposta dato che recentemente ho dovuto farlo e dopo aver provato diverse opzioni elencate da man verify, ho scoperto che il -untrustedparametro è quello corretto da utilizzare quando si specifica il certificato intermedio.
Anthony Geoghegan,

Penso che la seconda risposta: stackoverflow.com/a/31205833/173062 sia più accurata: passa la catena di certificati al parametro -CAfile.
Glenjamin,

2
-untrustednon controlla se la catena di certificati è completamente valida. Si prega di considerare di passare sia il comando intermedio che quello root al comando come -CAfilesuggeriscono altre domande.
Envek,

2
Usa -untrusted per Intermediate.pem se è possibile che si verifichi quanto segue: mail.python.org/pipermail/cryptography-dev/2016-agosto/…
Greg Smethells

2
Non è ciò che OP ha richiesto, ma nel caso in cui si desideri verificare la catena NON autofirmata, utilizzare il file CA del sistema / browser anziché il proprio. Ad esempio su OS X con openssl dall'uso dell'homebrew:openssl verify -CAfile /usr/local/etc/openssl/cert.pem -untrusted Intermediate.pem UserCert.pem
Greg Dubicki,

50

Questo è uno dei pochi lavori legittimi per cat:

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

Aggiornare:

Come sottolinea Greg Smethells nei commenti, questo comando si fida implicitamente di Intermediate.pem . Consiglio di leggere la prima parte dei riferimenti Greg post (la seconda parte riguarda specificamente pyOpenSSL e non è rilevante per questa domanda).

Nel caso in cui il post scompaia citerò i paragrafi importanti:

Sfortunatamente, un certificato "intermedio" che è in realtà una radice / autofirmato verrà trattato come una CA fidata quando si usa il comando raccomandato dato sopra:

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

Sembra che openssl smetterà di verificare la catena non appena viene rilevato un certificato radice, che può anche essere Intermediate.pem se è autofirmato. In tal caso, RootCert.pem non viene considerato. Quindi assicurati che Intermediate.pem provenga da una fonte attendibile prima di fare affidamento sul comando sopra.


Verificherà effettivamente il certificato intermedio rispetto al certificato radice?
augurar

Lo fa. Ho appena rieseguito i comandi con una catena che so essere corretta (serve il traffico di produzione per il mio datore di lavoro) e poi di nuovo con un altro certificato radice non correlato. Vedi l'essenza della trascrizione .
Peter,

8
ATTENZIONE: NON utilizzare questo se Intermediate.pem non è affatto affidabile. Per maggiori informazioni leggi qui: mail.python.org/pipermail/cryptography-dev/2016-agosto/…
Greg Smethells

1
Grazie per averlo sottolineato, Greg. Quando ho dato la risposta, ho scaricato sia le radici che gli intermedi dalle home page degli emittenti, quindi il pensiero non mi è venuto in mente. Ho aggiornato la risposta per chiarire che l'intermedio è implicitamente fidato di questo comando.
Peter,

1
@somenickname, vedi il commento di Tony. L'opzione -uggusted è comunque preferibile. Ti suggerisco di porre la tua domanda se desideri ulteriore aiuto. I commenti non sono il posto giusto per eseguire il debug del problema.
Peter,

17

Il problema è che openssl -verifynon fa il lavoro.

Come accennato da Priyadi , si openssl -verifyferma al primo certificato autofirmato, quindi non si verifica realmente la catena, poiché spesso il certificato intermedio è autofirmato.

Presumo che tu voglia essere sicuro al 101%, che i file del certificato siano corretti prima di provare a installarli nel servizio web produttivo. Questa ricetta qui esegue esattamente questo controllo pre-volo.

Si prega di notare che la risposta di Peter è corretta , tuttavia l'output di openssl -verifynon è un indizio del fatto che tutto in realtà dopo. Sì, potrebbe riscontrare alcuni problemi, ma non tutti.

Ecco uno script che fa il lavoro per verificare una catena di certificati prima di installarla in Apache. Forse questo può essere migliorato con alcune delle magie OpenSSL più mistiche, ma io non sono un guru OpenSSL e le seguenti opere:

#!/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

Nota che l'output successivo EVERYTHING OKè l'impostazione di Apache, perché anche le persone che usano NginXo di haproxysolito possono leggere e capire perfettamente;)

C'è un GitHub Gist di questo che potrebbe avere alcuni aggiornamenti

Prerequisiti di questo script:

  • Come al /etc/ssl/certssolito, hai i dati radice della CA attendibili, ad esempio su Ubuntu
  • Creare una directory in DIRcui archiviare 3 file:
    • DIR/certificate.crt che contiene il certificato
    • DIR/certificate.key che contiene la chiave segreta per il tuo servizio web (senza passphrase)
    • DIR/certificate.bundleche contiene il pacchetto CA. Su come preparare il pacchetto, vedi sotto.
  • Ora esegui lo script: ./check DIR/certificate(questo presuppone che lo script sia nominato checknella directory corrente)
  • C'è un caso molto improbabile che lo script produca CA-Bundle is not needed. Questo significa che tu (leggi:/etc/ssl/certs/ :) si fida già del certificato di firma. Ma questo è altamente improbabile nel WWW.
  • Per questo test la porta 4433 non deve essere utilizzata sulla workstation. E meglio eseguirlo solo in un ambiente sicuro, poiché apre la porta 4433 a breve al pubblico, che potrebbe vedere connessioni esterne in un ambiente ostile.

Come creare il file certificate.bundle file?

Nel WWW la catena di fiducia di solito assomiglia a questo:

  • certificato attendibile da /etc/ssl/certs
  • certificato / i intermedio / i sconosciuto / i, possibilmente con firma incrociata di un'altra CA.
  • il tuo certificato ( certificate.crt)

Ora, la valutazione si svolge dal basso verso l'alto, questo significa che prima viene letto il certificato, quindi è necessario il certificato intermedio sconosciuto, quindi forse il certificato di firma incrociata e quindi /etc/ssl/certs viene consultato per trovare il certificato attendibile corretto.

Il ca-bundle deve essere composto esattamente nel giusto ordine di elaborazione, questo significa che il primo certificato necessario (il certificato intermedio che firma il certificato) viene prima nel bundle. Quindi è necessario il cross-sign-cert.

Di solito la vostra CA (l'autorità che ha firmato il certificato) fornirà già un file ca-bundle adeguato. In caso contrario, è necessario selezionare tutti i certificati intermedi necessari e catriunirli in un unico file (su Unix). Su Windows puoi semplicemente aprire un editor di testo (come notepad.exe) e incollare i certificati nel file, il primo necessario in alto e seguire gli altri.

C'è un'altra cosa I file devono essere in formato PEM. Alcune CA rilasciano il formato DER (binario). PEM è facile da individuare: è leggibile ASCII. Per maggiori informazioni su come convertire qualcosa in PEM, vedi Come convertire .crt in .pem e seguire la strada di mattoni gialli.

Esempio:

Hai:

  • intermediate2.crt il certificato intermedio che ha firmato il tuo certificate.crt
  • intermediate1.crt un altro certificato intermedio, che cantava intermediate2.crt
  • crossigned.crt che è un certificato di firma incrociata di un'altra CA, che ha firmato intermediate1.crt
  • crossintermediate.crtche è un altro intermedio dall'altra CA che ha firmato crossigned.crt(probabilmente non vedrai mai una cosa del genere)

Quindi il proprio catdovrebbe apparire così:

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

E come puoi scoprire quali file sono necessari o meno e in quale sequenza?

Bene, sperimenta, fino a quando non checkti dice tutto è OK. È come un gioco puzzle per computer per risolvere l'enigma. Ogni. Singolo. Tempo. Anche per i professionisti. Ma migliorerai ogni volta che dovrai farlo. Quindi non sei assolutamente solo con tutto quel dolore. È SSL, lo sai? SSL è probabilmente uno dei peggiori progetti che abbia mai visto in oltre 30 anni di amministrazione professionale del sistema. Vi siete mai chiesti perché la criptovaluta non sia diventata mainstream negli ultimi 30 anni? Ecco perchè. 'ha detto Nuff.


Al downvoter: per favore, spiega cosa non va nella mia risposta. Grazie.
Tino,

2
Sono uno dei downvoter. Ciò che ha innescato il downvote è questo: "E come puoi scoprire quali file sono necessari o meno e in quale sequenza? Bene, sperimenta, fino a quando il controllo ti dice che tutto è OK". Non credo che SSL sia un caso speciale. Problemi come questo dovrebbero avere una soluzione deterministica.
ychaouche,

2
@ychaouche Grazie! Mi piacciono le cose desterministe. La domanda era: "Che cosa c'è che non va" e come farlo con "openssl verifica". Dato che siamo su StackOverflow, ho spiegato che, seguito da una risposta sì / no programmatica (quindi deterministica). Puoi persino usarlo per automatizzare i controlli per il nuovo pacchetto prima di installarlo in produzione. Questo risponde pienamente alla domanda. Quello che non ti piace è che ho parlato della frustrazione su "Come creare un pacchetto adeguato?". Dal momento che penso che non ci possa essere una breve risposta deterministica per questo, rispondere a questo sarebbe offtopico nel contesto qui.
Tino,

6
"Come accennato da Priyadi, openssl -verify si ferma al primo certificato autofirmato, quindi non si verifica realmente la catena, poiché spesso il certificato intermedio è autofirmato." Ovviamente i certificati intermedi non sono mai autofirmati (se lo fossero, sarebbero certificati root). E l'intero punto di verifica è verificare di aver incluso tutti i certificati nella catena fino a un certificato radice attendibile. Questo è esattamente ciò che verifica openssl. Tuttavia, openssl tende ad essere piuttosto conservatore con le sue politiche di fiducia ...
Timo,

4
"spesso il certificato intermedio è autofirmato". Questo è sbagliato e confusioni terminologiche come questa rendono difficile per i nuovi arrivati ​​comprendere un argomento che in realtà è piuttosto semplice quando spiegato nel modo giusto. Da RFC 5280: "[...] i certificati CA possono essere ulteriormente suddivisi in tre classi: certificati incrociati, certificati emessi e certificati autofirmati. I certificati incrociati sono certificati CA in cui l'emittente e l'oggetto sono entità diverse I certificati incrociati descrivono una relazione di fiducia tra le due autorità di certificazione. [...] ".
Dr. Jan-Philip Gehrcke,

8

Ho dovuto fare una verifica di un certificato letsencrypt e l'ho fatto in questo modo:

  1. Scarica root-cert e intermedio-cert dalla catena di fiducia letsencrypt .
  2. Emetti questo 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
    

1
Beh, sembra che a John non sia piaciuto quello che ho detto grazie. Insisto sul duro "Grazie", quindi ecco il testo cancellato: spero che ti aiuti per i tuoi permessi di crittografia. Grazie per Priyadi, la tua soluzione mi ha aiutato a trovare questo comando. Assicurati di votare la sua soluzione.
Michael,

5

Dopo aver interrotto un'intera giornata con lo stesso identico problema, senza alcuna conoscenza precedente dei certificati SSL, ho scaricato CERTivity Keystores Manager e importato il mio keystore su di esso, ottenendo una visualizzazione chiara della catena di certificati.

Immagine dello schermo :

inserisci qui la descrizione dell'immagine


1
Non cerca di rispondere alla domanda su come utilizzare openssl verify.
binki,

sì, ma questo tipo di strumento può darti la visualizzazione necessaria di quel tipo di cose se non capisci le informazioni criptiche degli strumenti della riga di comando di openssl :) Quindi ecco il mio voto, ci potrebbero essere alcune cose online che lo fanno anche.
David 天宇 Wong,

2

Se vuoi solo verificare che l' emittente di UserCert.pem sia effettivamente Intermediate.pem il seguente (l'esempio usa:) OpenSSL 1.1.1:

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

e otterrai:

UserCert.pem: OK

o

UserCert.pem: verification failed

esiste un comando equivalente per openssl verify -no-CAfile -no-CApath -partial_chain -trusted Intermediate.pem UserCert.pemin Python 3.7?
Bogota,

-5

Puoi facilmente verificare una catena di certificati con openssl. Il fullchain includerà il certificato CA quindi dovresti vedere i dettagli sulla CA e sul certificato stesso.

openssl x509 -in fullchain.pem -text -noout


4
1) Questo è del tutto senza alcun tipo di spiegazione. 2) questa è una risposta a una domanda che il richiedente non ha posto, senza alcun contesto.
Shadur,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.