Wie extrahiere ich die Stammzertifizierungsstelle und die untergeordnete Zertifizierungsstelle aus einer Zertifikatskette in Linux?

Wie extrahiere ich die Stammzertifizierungsstelle und die untergeordnete Zertifizierungsstelle aus einer Zertifikatskette in Linux?

Ich habe ein End-Entity-/Server-Zertifikat mit einem Zwischen- und einem Stammzertifikat. Wenn ich catauf das End-Entity-Zertifikat klicke, sehe ich nur ein einzelnes BEGINTag END. Es ist das einzige End-Entity-Zertifikat.

Gibt es eine Möglichkeit, den Inhalt des Zwischen- und Stammzertifikats anzuzeigen? Ich benötige nur den Inhalt BEGINund ENDdas Tag.

In Windows kann ich die vollständige Zertifikatskette im „Zertifizierungspfad“ sehen. Unten sehen Sie das Beispiel für das Stack Exchange-Zertifikat.

Bildbeschreibung hier eingeben

Von dort aus kann ich eineZertifikat ansehenund sie exportieren. Ich kann das sowohl für Root als auch für Zwischenbenutzer in Windows tun. Ich suche nach derselben Methode in Linux.

Bildbeschreibung hier eingeben

Antwort1

Von einer Website aus können Sie Folgendes tun:

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

Dadurch werden die Zertifikatskette und alle vom Server vorgelegten Zertifikate angezeigt.

Wenn ich diese beiden Zertifikate jetzt in Dateien speichere, kann ich Folgendes verwenden 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

Die -untrustedOption wird verwendet, um das/die Zwischenzertifikat(e) anzugeben; se.crtist das zu überprüfende Zertifikat. Das Ergebnis „Tiefe=2“ stammt aus dem vertrauenswürdigen CA-Speicher des Systems.

Wenn Sie die Zwischenzertifikate nicht haben, können Sie die Überprüfung nicht durchführen. So funktioniert X.509 nun einmal.

openssl x509 -in se.crt -noout -textJe nach Zertifikat kann es eine URI enthalten, von der das Zwischenzertifikat abgerufen werden kann. Enthält beispielsweise :

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

Diese „CA Issuers“-URI verweist auf das Zwischenzertifikat (im DER-Format, Sie müssen openssl x509 -inform der -in DigiCertSHA2HighAssuranceServerCA.crt -out DigiCertSHA2HighAssuranceServerCA.pemes also für die weitere Verwendung durch OpenSSL konvertieren).

Wenn Sie ausführen , openssl x509 -in /tmp/DigiCertSHA2HighAssuranceServerCA.pem -noout -issuer_hasherhalten Sie 244b5494, wonach Sie im Stamm-CA-Speicher des Systems unter suchen können /etc/ssl/certs/244b5494.0(einfach .0an den Namen anhängen).

Ich glaube nicht, dass es einen schönen, einfachen OpenSSL-Befehl gibt, der das alles für Sie erledigt.

Antwort2

tl;dr - Einzeiler-Bash-Magie, um alle Zertifikate in der Kette zu entleeren

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

Erklärung in 2 Schritten

Um alle Zertifikate in der Kette wie folgt in das aktuelle Verzeichnis zu übertragen 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}' 

Der Bonustrack zur Umbenennung in ihre gebräuchlichen Namen:

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

Antwort3

Ich habe herausgefunden, dass -verify 5OpenSSL mit der Option tief in die Kette eindringt und alle Zertifikate anzeigt, auch diejenigen, die nicht in Ihrer Zertifikatsbereitstellung enthalten sind.

Wenn Sie wirklich verstehen möchten, welche Kette mit Ihrem Zertifikat bereitgestellt wird, sollten Sie Folgendes ausführen:

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

Antwort4

Das oben genannte hat bei mir nicht funktioniert, als ich ein kostenloses Wildcard-Zertifikat von Lets Encrypt verwendet habe.

Genauer gesagt:
Ich habe einen Kubernetes-Cluster + Ingress-Controller, der mit einem kostenlosen Wildcard-Zertifikat von Lets Encrypt für *.mydomain.dev konfiguriert ist und die folgenden 2 Domänennamen hostet:

  • grafana.meinedomain.dev
  • prometheus.mydomain.dev

Ich musste das Flag -servername gemäß dieser Site wie folgt hinzufügen: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}'

Ich habe außerdem die Kette optimiert, sodass sie mir das vollständige Zertifikat + Zwischenzertifikat + Root für die Standardausgabe gibt und das Stderr-Rauschen ausblendet.

Tatsächlich ... habe ich beim Testen festgestellt, dass ich dadurch nicht die CA bekomme ... 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 Gibt einen anderen Wert zurück (und beim Testen einiger Dinge ist dies der Wert, der funktioniert.)

verwandte Informationen