如何在 Linux 中從憑證鏈中提取根 CA 和從屬 CA?

如何在 Linux 中從憑證鏈中提取根 CA 和從屬 CA?

我有一個終端實體/伺服器證書,其中包含中間證書和根證書。當我cat在最終實體憑證上時,我只看到一個BEGINEND標籤。它是唯一的最終實體憑證。

有什麼方法可以查看中間證書和根證書內容。我只需要BEGIN和標籤的內容END

在 Windows 中,我可以從「憑證路徑」看到完整的憑證鏈。以下是 Stack Exchange 憑證的範例。

在此輸入影像描述

從那裡我可以執行查看證書並導出它們。我可以在 Windows 中對根目錄和中間目錄執行此操作。我正在Linux中尋找同樣的方法。

在此輸入影像描述

答案1

從網站上,您可以執行以下操作:

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

這將顯示憑證鍊和伺服器提供的所有憑證。

現在,如果我將這兩個證書保存到文件中,我可以使用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

-untrusted選項用於提供中間證書;se.crt是要驗證的證書。深度=2的結果來自系統信任的CA儲存。

如果您沒有中間證書,則無法執行驗證。這就是 X.509 的工作原理。

根據證書的不同,它可能包含從中獲取中間體的 URI。例如,openssl x509 -in se.crt -noout -text包含:

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

這個「CA Issuers」URI 指向中間憑證(採用 DER 格式,因此您需要使用openssl x509 -inform der -in DigiCertSHA2HighAssuranceServerCA.crt -out DigiCertSHA2HighAssuranceServerCA.pem它來轉換它以供 OpenSSL 進一步使用)。

如果運行,openssl x509 -in /tmp/DigiCertSHA2HighAssuranceServerCA.pem -noout -issuer_hash您會得到244b5494,您可以在系統根 CA 儲存中找到它/etc/ssl/certs/244b5494.0(只需附加.0到名稱)。

我認為沒有一個好的、簡單的 OpenSSL 命令可以為您完成所有這些工作。

答案2

tl;dr - 一個 liner bash 魔法可以轉儲鏈中的所有憑證

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

分2步驟解釋

若要將鏈中的所有憑證轉儲到目前目錄,如下所示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}' 

將它們重新命名為通用名稱的獎勵曲目:

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

答案3

我發現使用選項-verify 5openssl 會深入顯示所有證書,甚至不包含在您的證書部署中。

如果您確實想了解您的憑證提供了哪個鏈,您應該運行:

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

答案4

當我使用 Lets Encrypt 免費通配符憑證時,上述方法對我不起作用。

更具體地說:
我有一個 Kubernetes 叢集 + 入口控制器,它使用 *.mydomain.dev 的 Lets Encrypt 免費通配符憑證進行配置,它託管以下 2 個網域:

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

我必須在每個網站後面添加 -servername 標誌: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}'

我還調整了鏈,因此它為我提供了標準輸出的完整證書+中間+根並隱藏stderr噪音。

實際上......測試時我發現這並沒有給我CA...... 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 給出不同的值(當測試某些東西時,這是有效的值。)

相關內容