Linuxの証明書チェーンからルートCAとサブCAを抽出する方法は?

Linuxの証明書チェーンからルートCAとサブCAを抽出する方法は?

中間証明書とルート証明書を含む最終的なエンティティ/サーバー証明書があります。cat最終エンティティ証明書にはラベルとラベルのみが表示されBEGINますEND。唯一の最終エンティティ証明書です。

中間証明書とルート証明書の内容を表示する方法はありますか?私はちょうどBEGIN内容を必要とラベルを指定しますEND

Windowsでは、「証明書パス」で証明書チェーン全体を表示できます。以下は、Stack Exchange 証明書の例です。

ここに画像の説明を入力してください。

そこから私は実行できます証明書の表示そしてエクスポートします。 Windowsでは、ルートディレクトリと中間ディレクトリに対してこれを行うことができます。 Linuxでも同じ方法を探しています。

ここに画像の説明を入力してください。

答え1

Webサイトで次のことができます。

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

これにより、サーバーが提供する証明書チェーンとすべての証明書が表示されます。

2つの証明書をファイルに保存すると、次のことができます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

openssl x509 -inform der -in DigiCertSHA2HighAssuranceServerCA.crt -out DigiCertSHA2HighAssuranceServerCA.pem「CA発行者」URIは中間証明書(DER形式であるため、OpenSSLで後で使用するにはそれを変換するために使用する必要があります)を指します。

これを実行すると、システムルートCAストアにありますopenssl x509 -in /tmp/DigiCertSHA2HighAssuranceServerCA.pem -noout -issuer_hash(名前に追加するだけです)。244b5494/etc/ssl/certs/244b5494.0.0

これをすべて行うことができる素晴らしいシンプルなOpenSSLコマンドはないと思います。

答え2

tl;dr - チェーン内のすべての証明書をダンプするライナー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無料のワイルドカード証明書を使用すると、上記の方法は機能しません。

具体的には、
次の2つのドメインをホストする* .mydomain.devのLets Encrypt無料ワイルドカード証明書で構成されているKubernetesクラスター+受信コントローラーがあります。

  • 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}'

また、チェーンを調整してstdoutの完全な証明書+中間+ルートを提供し、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 別の値を指定してください。 (何かをテストするときに有効な値です。)

関連情報