Zweryfikuj łańcuch certyfikatów za pomocą openssl verify

128

Buduję własny łańcuch certyfikatów z następującymi komponentami:

Root Certificate - Intermediate Certificate - User Certificate

Certyfikat Root jest certyfikatem z podpisem własnym, Certyfikat pośredni jest podpisany przez użytkownika głównego, a użytkownik przez pośrednika.

Teraz chcę sprawdzić, czy certyfikat użytkownika ma swoją kotwicę przez certyfikat główny.

Z

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

walidacja jest w porządku. W następnym kroku potwierdzam certyfikat użytkownika za pomocą

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

a walidacja pokazuje

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

Co jest nie tak?

Indra
źródło

Odpowiedzi:

164

Z verifydokumentacji:

Jeśli zostanie znaleziony certyfikat, który jest jego własnym wystawcą, przyjmuje się, że jest to główny urząd certyfikacji.

Innymi słowy, główny urząd certyfikacji musi podpisać się samemu, aby weryfikacja działała. Dlatego twoje drugie polecenie nie zadziałało. Spróbuj tego zamiast tego:

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

Sprawdzi cały łańcuch za pomocą jednego polecenia.

Priyadi
źródło
2
Głosuję za tą odpowiedzią, ponieważ ostatnio musiałem to zrobić i po wypróbowaniu różnych opcji wymienionych przez man verifystwierdziłem, że -untrustedparametr jest prawidłowy do użycia podczas określania certyfikatu pośredniego.
Anthony Geoghegan
Myślę, że druga odpowiedź: stackoverflow.com/a/31205833/173062 jest dokładniejsza - przekazuje łańcuch certyfikatów do parametru -CAfile.
Glenjamin
2
-untrustednie sprawdza, czy łańcuch certyfikatów jest w pełni ważny. Rozważ przekazanie do polecenia zarówno pośredniego, jak i głównego, tak -CAfilejak sugerują inne pytania.
Envek
2
Użyj -niezaufany dla pośredniego.pem, jeśli jest możliwe, że wydarzy się co następuje: mail.python.org/pipermail/cryptography-dev/2016-August/ ...
Greg Smethells
2
Nie o to prosił OP, ale jeśli chcesz zweryfikować łańcuch NIE z podpisem własnym, użyj pliku CA systemu / przeglądarki zamiast własnego. Na przykład na OS X z openssl z homebrew użyj:openssl verify -CAfile /usr/local/etc/openssl/cert.pem -untrusted Intermediate.pem UserCert.pem
Greg Dubicki
50

To jedna z niewielu legalnych ofert pracy dla cat:

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

Aktualizacja:

Jak Greg Smethells zwraca uwagę w komentarzach, to polecenie niejawnie ufa plikowi Intermediate.pem . Polecam przeczytanie pierwszej części wpisu Grega (druga część dotyczy konkretnie pyOpenSSL i nie dotyczy tego pytania).

Na wypadek, gdyby post zniknął, zacytuję ważne akapity:

Niestety, „pośredni” certyfikat, który w rzeczywistości jest rootem / z podpisem własnym będzie traktowany jako zaufany urząd certyfikacji, jeśli użyjesz zalecanego polecenia podanego powyżej:

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

Wygląda na to, że openssl przestanie weryfikować łańcuch, gdy tylko napotkany zostanie certyfikat główny, którym może być również plik pośredni.pem, jeśli jest samopodpisany. W takim przypadku RootCert.pem nie jest brany pod uwagę. Dlatego upewnij się, że plik Intermediate.pem pochodzi z zaufanego źródła, zanim skorzystasz z powyższego polecenia.

Piotr
źródło
Czy to faktycznie zweryfikuje certyfikat pośredni względem certyfikatu głównego?
augurar
To robi. Po prostu ponownie uruchomiłem polecenia z łańcuchem, o którym wiem, że jest poprawny (obsługuje ruch produkcyjny dla mojego pracodawcy), a następnie ponownie z innym, niepowiązanym certyfikatem głównym. Zobacz sedno transkrypcji .
Peter,
8
OSTRZEŻENIE: NIE używaj tego, jeśli plik Intermediate.pem jest w ogóle niezaufany. Więcej informacji można znaleźć tutaj: mail.python.org/pipermail/cryptography-dev/2016-August/ ...
Greg Smethells
1
Dzięki za zwrócenie uwagi Greg. Kiedy udzieliłem odpowiedzi, pobrałem zarówno korzenie, jak i półprodukty ze stron głównych wydawców, więc ta myśl nie przyszła mi do głowy. Zaktualizowałem odpowiedź, aby wyjaśnić, że to polecenie pośrednio jest zaufane.
Peter
1
@somenickname, zobacz komentarz Tony'ego. W każdym razie opcja niezaufana jest lepsza. Proponuję zadać własne pytanie, jeśli potrzebujesz dalszej pomocy. Komentarze nie są odpowiednim miejscem do debugowania problemu.
Peter
17

Problemem jest openssl -verify to nie działa.

Jak wspomniała Priyadi , openssl -verifyzatrzymuje się na pierwszym samopodpisanym certyfikacie, dlatego tak naprawdę nie weryfikujesz łańcucha, ponieważ często certyfikat pośredni jest samopodpisany.

Zakładam, że chcesz mieć 101% pewności, że pliki certyfikatów są poprawne, zanim spróbujesz je zainstalować w produktywnej usłudze sieciowej. Ten przepis tutaj przeprowadza dokładnie tę kontrolę przed lotem.

Proszę zauważyć, że odpowiedź Piotra jest poprawna , jednak wynik openssl -verifynie jest wskazówką, że wszystko naprawdę działa później. Tak, może napotkać pewne problemy, ale nie wszystkie.

Oto skrypt, który wykonuje zadanie weryfikacji łańcucha certyfikatów przed zainstalowaniem go w Apache. Być może można to ulepszyć za pomocą bardziej mistycznej magii OpenSSL, ale nie jestem guru OpenSSL i następujące prace:

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

Zwróć uwagę, że dane wyjściowe po EVERYTHING OK to ustawienie Apache, ponieważ ludzie używający NginXlub haproxyzwykle potrafią to doskonale przeczytać i zrozumieć;)

Istnieje GitHub Gist tego, który może zawierać pewne aktualizacje

Wymagania wstępne tego skryptu:

  • Masz zaufane dane głównego urzędu certyfikacji w /etc/ssl/certs jak zwykle, na przykład w systemie Ubuntu
  • Utwórz katalog DIR którym przechowujesz 3 pliki:
    • DIR/certificate.crt który zawiera certyfikat
    • DIR/certificate.key który zawiera tajny klucz do Twojej usługi internetowej (bez hasła)
    • DIR/certificate.bundlektóry zawiera pakiet CA. O tym, jak przygotować pakiet, patrz poniżej.
  • Teraz uruchom skrypt: ./check DIR/certificate(przy założeniu, że skrypt ma nazwęcheck w bieżącym katalogu)
  • Istnieje bardzo mało prawdopodobny przypadek, że skrypt wyświetli wynik CA-Bundle is not needed. Oznacza to, że ty (czytaj:/etc/ssl/certs/ :) już ufasz certyfikatowi podpisującemu. Ale jest to mało prawdopodobne w sieci WWW.
  • Na potrzeby tego testu port 4433 musi być nieużywany na stacji roboczej. I lepiej uruchamiać to tylko w bezpiecznym środowisku, ponieważ otwiera port 4433 wkrótce dla publiczności, która może zobaczyć obce połączenia w wrogim środowisku.

Jak stworzyć certificate.bundle plik?

W sieci WWW łańcuch zaufania zwykle wygląda następująco:

  • zaufany certyfikat od /etc/ssl/certs
  • nieznane certyfikaty pośrednie, prawdopodobnie podpisane krzyżowo przez inny CA
  • twój certyfikat ( certificate.crt)

Teraz ocena odbywa się od dołu do góry, co oznacza, że ​​najpierw czytany jest twój certyfikat, potem potrzebny jest nieznany certyfikat pośredni, potem być może certyfikat cross-podpisujący, a następnie /etc/ssl/certs konsultowany jest w celu znalezienia odpowiedniego zaufanego certyfikatu.

Ca-bundle musi być skomponowane w dokładnie odpowiedniej kolejności przetwarzania, co oznacza, że ​​pierwszy potrzebny certyfikat (certyfikat pośredni, który podpisuje Twój certyfikat) jest na pierwszym miejscu w pakiecie. Wtedy potrzebny jest certyfikat do podpisu krzyżowego.

Zwykle Twój CA (urząd, który podpisał Twój certyfikat) dostarcza już taki właściwy plik ca-bundle. Jeśli nie, musisz zebrać wszystkie potrzebne certyfikaty pośrednie i catzebrać je razem w jednym pliku (w systemie Unix). W systemie Windows możesz po prostu otworzyć edytor tekstu (np. notepad.exe) I wkleić certyfikaty do pliku, pierwszy potrzebny na górze i po pozostałych.

Jest jeszcze jedna rzecz. Pliki muszą być w formacie PEM. Niektóre urzędy certyfikacji wydają format DER (binarny). PEM jest łatwy do wykrycia: jest czytelny w ASCII. Aby dowiedzieć się, jak przekonwertować coś na PEM, zobacz Jak przekonwertować .crt na .pem i podążaj żółtą ceglaną drogą.

Przykład:

Ty masz:

  • intermediate2.crt certyfikat pośredni, który podpisał twój certificate.crt
  • intermediate1.crt kolejny certyfikat pośredni, który spalił intermediate2.crt
  • crossigned.crt który jest certyfikatem do podpisywania krzyżowego z innego urzędu certyfikacji, który podpisał intermediate1.crt
  • crossintermediate.crtktóry jest kolejnym pośrednikiem z innego CA, który podpisał crossigned.crt(prawdopodobnie nigdy czegoś takiego nie zobaczysz)

Wtedy właściwy catwyglądałby tak:

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

Jak możesz dowiedzieć się, które pliki są potrzebne, a które nie iw jakiej kolejności?

Cóż, eksperymentuj, dopóki nie checkpowie ci, że wszystko jest w porządku. To jak gra logiczna na komputerze, w której rozwiązuje się zagadkę. Każdy. Pojedynczy. Czas. Nawet dla profesjonalistów. Ale za każdym razem, gdy będziesz tego potrzebować, będziesz coraz lepszy. Więc definitywnie nie jesteś sam z całym tym bólem. To SSL, wiesz? SSL to prawdopodobnie jeden z najgorszych projektów, jakie widziałem w ciągu ponad 30 lat profesjonalnej administracji systemem. Czy zastanawiałeś się kiedyś, dlaczego kryptowaluty nie stały się głównym nurtem w ciągu ostatnich 30 lat? Dlatego. - powiedział nuff.

Tino
źródło
Do zwolennika krytyki: proszę wyjaśnić, co jest nie tak w mojej odpowiedzi. Dzięki.
Tino
2
Jestem jednym z przeciwników. To, co wywołało głosowanie przeciwne, to: "A jak możesz dowiedzieć się, które pliki są potrzebne, a które nie iw jakiej kolejności? Cóż, eksperymentuj, aż sprawdzenie powie ci, że wszystko jest w porządku". Nie sądzę, aby SSL był szczególnym przypadkiem. Takie problemy powinny mieć deterministyczne rozwiązanie.
ychaouche
2
@ychaouche Thanks! Tak jak ty lubię desterministyczne rzeczy. Pytanie brzmiało „Co jest nie tak” i jak to zrobić za pomocą „openssl verify”. Ponieważ korzystamy z przepełnienia stosu, wyjaśniłem to, po czym nastąpiła programowa (a więc deterministyczna) odpowiedź tak / nie. Możesz nawet użyć go do zautomatyzowania kontroli nowego pakietu przed zainstalowaniem go w środowisku produkcyjnym. To w pełni odpowiada na pytanie. Nie podoba ci się to, że opowiedziałem o frustracji na temat „Jak stworzyć odpowiedni pakiet?”. Ponieważ myślę, że nie może być na to krótkiej deterministycznej odpowiedzi, odpowiedź na to pytanie byłaby offtopic w kontekście tutaj.
Tino
6
„Jak wspomniała Priyadi, openssl -verify zatrzymuje się na pierwszym samopodpisanym certyfikacie, dlatego tak naprawdę nie weryfikujesz łańcucha, ponieważ często pośredni certyfikat jest samopodpisany”. Oczywiście certyfikaty pośrednie nigdy nie są podpisywane samodzielnie (gdyby były certyfikatami głównymi). Cały punkt weryfikacji polega na sprawdzeniu, czy wszystkie certyfikaty zostały uwzględnione w łańcuchu, aż do zaufanego certyfikatu głównego. Właśnie to robi weryfikacja openssl. Jednak openssl wydaje się być raczej konserwatywny ze swoją ufną polityką ...
Timo
4
„często certyfikat pośredni jest samopodpisany”. To jest złe, a niejasności terminologiczne, takie jak ten, utrudniają nowoprzybyłym zrozumienie tematu, który w rzeczywistości jest raczej prosty, gdy zostanie wyjaśniony we właściwy sposób. Z RFC 5280: „[...] certyfikaty CA można dalej podzielić na trzy klasy: certyfikaty krzyżowe, certyfikaty wystawiane przez siebie i certyfikaty z podpisem własnym. Certyfikaty krzyżowe to certyfikaty CA, w których wystawcą i podmiotem są różne jednostki . Certyfikaty krzyżowe opisują relację zaufania między dwoma urzędami certyfikacji. [...] ”.
Dr Jan-Philip Gehrcke
8

Musiałem dokonać weryfikacji certyfikatu letsencrypt i zrobiłem to tak:

  1. Pobierz certyfikat główny i certyfikat pośredni z łańcucha zaufania letsencrypt .
  2. Wydaj to polecenie:

    $ 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
    
Michael
źródło
1
Cóż, wygląda na to, że Johnowi nie podobało się to, że dziękuję. Nalegam na trudne „Dziękuję”, więc oto usunięty tekst: Mam nadzieję, że pomoże Ci to w uzyskaniu certyfikatów LetSencrypt. Dzięki za Priyadi, twoje rozwiązanie pomogło mi znaleźć to polecenie. Zagłosuj za jego rozwiązaniem.
Michael
5

Po spędzeniu całego dnia na dokładnie tym samym problemie, bez wcześniejszej wiedzy na temat certyfikatów SSL, pobrałem CERTivity Keystores Manager i zaimportowałem do niego mój magazyn kluczy i otrzymałem przejrzystą wizualizację łańcucha certyfikatów.

Zrzut ekranu :

wprowadź opis obrazu tutaj

praveen.chandran
źródło
1
Nie próbuje odpowiedzieć na pytanie, jak używać openssl verify.
binki
tak, ale tego rodzaju narzędzie może dać ci potrzebną wizualizację tego rodzaju rzeczy, jeśli nie rozumiesz tajemniczych informacji narzędzi wiersza poleceń openssl :) Więc oto moja opinia, mogą być też rzeczy online, które to robią.
David 天宇 Wong
2

Jeśli chcesz tylko sprawdzić, czy emitent z UserCert.pem faktycznie Intermediate.pem zrobić następująco (przykład zastosowania: OpenSSL 1.1.1):

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

a otrzymasz:

UserCert.pem: OK

lub

UserCert.pem: verification failed
Marinos An
źródło
czy jest jakieś równoważne polecenie openssl verify -no-CAfile -no-CApath -partial_chain -trusted Intermediate.pem UserCert.pemw Pythonie 3.7?
Bogota
-5

Możesz łatwo zweryfikować łańcuch certyfikatów za pomocą openssl. Pełny łańcuch będzie zawierał certyfikat CA, więc powinieneś zobaczyć szczegółowe informacje o CA i samym certyfikacie.

openssl x509 -in fullchain.pem -text -noout

jorfus
źródło
4
1) Jest to całkowicie bez żadnego wyjaśnienia. 2) jest to odpowiedź na pytanie, którego pytający nie zadał, bez kontekstu.
Shadur