web-dev-qa-db-ja.com

openssl verifyを使って証明書チェーンを検証する

以下のコンポーネントで独自の証明書チェーンを構築しています。
Root Certificate - Intermediate Certificate - User Certificate
ルート証明書は自己署名証明書で、中間証明書はルートによって、ユーザーは中間者によって署名されています。

それでは、ユーザー証明書にルート証明書によるアンカーがあるかどうかを確認します。

あり
openssl verify -verbose -CAfile RootCert.pem Intermediate.pem
検証は問題ありません。次のステップで、ユーザー証明書を検証します。
openssl verify -verbose -CAfile Intermediate.pem UserCert.pem
および検証で、深さ0の検索でエラー20が表示されます。ローカル発行者証明書を取得できません

なにが問題ですか?

101
Indra

「検証」ドキュメントから:「それ自身の発行者である証明書が見つかった場合、それはルートCAであると見なされます」。言い換えれば、ルートCAは検証のために自己署名する必要があります。これが、2番目のコマンドが機能しなかった理由です。

代わりにこれを試してください:

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

チェーン全体を単一のコマンドで検証します。

119
Priyadi

これはcatの数少ない正当な仕事の1つです。

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

更新:

Greg Smethellsがコメントで指摘しているように、このコマンドは暗黙的にIntermediate.pemを信頼しています。私は ポストGreg参照 の最初の部分を読むことをお勧めします(2番目の部分は特にpyOpenSSLに関するもので、この質問には関係ありません)。

投稿がなくなった場合は、重要な段落を引用します。

残念ながら、実際にはルート/自己署名である「中間」証明書は、上記の推奨コマンドを使用すると信頼できるCAとして扱われます。

$ openssl verify -CAファイル<(cat geotrust_global_ca.pem rogue_ca.pem)fake_sometechcompany_from_rogue_ca.com.pem fake_sometechcompany_from_rogue_ca.com.pem:OK

Opensslはルート証明書が見つかるとすぐにチェーンの検証を中止するようです。これは自己署名されていればIntermediate.pemでも構いません。その場合、RootCert.pemは考慮されません。そのため、上記のコマンドに依存する前に、Intermediate.pemが信頼できるソースから送信されていることを確認してください。

39
Peter

問題は、openssl -verifyが仕事をしないということです。

プリヤディが述べたようにopenssl -verifyは最初の自己署名証明書で停止します。したがって、中間証明書は自己署名されることが多いため、実際にチェーンを検証することはありません。

実稼働Webサービスに証明書ファイルをインストールする前に、証明書ファイルが正しいことを101%確認したいと思います。ここでのこのレシピは、まさにこのプリフライトチェックを実行します。

Peterの答えは正しい ですが、openssl -verifyの出力はすべてreallyが後で機能するという手掛かりではないことに注意してください。はい、いくつかの問題が見つかるかもしれませんが、すべてではありません。

Apacheにインストールする前に証明書チェーンを検証するジョブを実行するスクリプトを次に示します。おそらくこれは、より神秘的なOpenSSLマジックのいくつかで強化することができますが、私はOpenSSLの第一人者ではなく、次の作品です。

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

EVERYTHING OKの後の出力はApacheの設定であることに注意してください。これは、NginXまたはhaproxyを使用している人も通常、これを完全に読み取って理解できるためです;)

GitHub Gist があり、これにはいくつかの更新がある可能性があります

このスクリプトの前提条件:

  • Ubuntuの例のように、信頼できるCAルートデータは/etc/ssl/certsにあります
  • 3つのファイルを保存するディレクトリDIRを作成します:
    • DIR/certificate.crt証明書を含む
    • DIR/certificate.keyは、Webサービスの秘密鍵を含みます(パスフレーズなし)
    • DIR/certificate.bundle CAバンドルが含まれています。バンドルの準備方法については、以下を参照してください。
  • 次に、スクリプトを実行します:./check DIR/certificate(これは、スクリプトの名前が現在のディレクトリでcheckであると想定しています)
  • スクリプトがCA-Bundle is not neededを出力するという非常にまれなケースがあります。つまり、あなたは(読み取り:/etc/ssl/certs/)すでに署名証明書を信頼しています。しかし、これはWWWでは非常にまれです。
  • このテストでは、ワークステーションでポート4433を使用する必要があります。また、これは安全な環境でのみ実行することをお勧めします。これは、ポート4433をすぐに公開し、敵対的な環境で外部接続を確認する可能性があるためです。

certificate.bundleファイルの作成方法

WWWでは、トラストチェーンは通常次のようになります。

  • /etc/ssl/certsからの信頼できる証明書
  • 不明な中間証明書、別のCAによって相互署名されている可能性があります
  • 証明書(certificate.crt

ここで、評価は下から上に行われます。つまり、最初に証明書が読み取られ、次に不明な中間証明書が必要になり、次にクロス署名証明書が必要になり、/etc/ssl/certsが適切なものを見つけるために調べられます。信頼できる証明書。

Caバンドルは、正確に正しい処理順序で構成する必要があります。つまり、最初に必要な証明書(証明書に署名する中間証明書)がバンドルの最初に来ます。次に、相互署名証明書が必要です。

通常、CA(証明書に署名した機関)は、そのような適切なca-bundle-fileをすでに提供しています。そうでない場合は、必要なすべての中間証明書を選択し、catを一緒にして1つのファイルに(Unixで)する必要があります。 Windowsでは、テキストエディター(notepad.exeなど)を開き、証明書をファイルに貼り付けることができます。

別のことがあります。ファイルはPEM形式である必要があります。一部のCAはDER(バイナリ)形式を発行します。 PEMは簡単に見つけることができます。ASCII読み取り可能です。何かをPEMに変換する方法については、 。crtを.pemに変換する方法 を参照し、黄色いレンガの道を進んでください。

例:

あなたが持っている:

  • intermediate2.crtcertificate.crtに署名した中間証明書
  • intermediate1.crt別の中間証明書、歌ったintermediate2.crt
  • crossigned.crtこれは、intermediate1.crtに署名した別のCAからの相互署名証明書です
  • crossintermediate.crtは、crossigned.crtに署名した他のCAの別の中間体です(おそらく、このようなことは決してありません)

次に、適切なcatは次のようになります。

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

また、どのファイルが必要かどうか、どの順序でどのように見つけることができますか?

checkがすべて問題ないことを示すまで、実験してください。それは謎を解くためのコンピューターパズルゲームのようなものです。すべて。シングル。時間。プロでも。しかし、これを行う必要があるたびに良くなります。ですから、あなたは間違いなくそのすべての痛みを抱えているだけではありません。それはSSLだ、知ってる? SSLはおそらく、30年以上にわたる専門的なシステム管理で見た最悪の設計の1つです。過去30年間で暗号が主流にならなかった理由を疑問に思ったことはありませんか?それが理由です。 '言っ途切れる。

13
Tino

私はletsencrypt証明書の検証をしなければなりませんでした、そして私はそれをこのようにしました:

  1. ルート証明書と中間証明書をletsencrypt信頼チェーンからダウンロードします。 https://letsencrypt.org/certificates/
  2. このコマンドを発行して下さい:

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

それがあなたのletsencrypt証明書のためにあなたを助けることを願っています。 Priyadiをありがとう、あなたの解決策は私がこの命令を見つけるのを助けました。彼の解決策を確実に支持してください。

5
Michael

SSL証明書に関する予備知識がなくても、まったく同じ問題で一日中壊れた後、 CERTivity Keystores Manager をダウンロードし、それに自分のキーストアをインポートしました。証明書チェーンを明確に視覚化しました。

スクリーンショット

enter image description here

3