サーバーのセットアップ方法と、サーバーのhello証明書メッセージ中に実際に送信される証明書について、私は誤った印象を持っている可能性があります。今日、これはSymantec/VeriSignから出会いました。
サーバーにインストールされているルート。ベストプラクティスとして、サーバーから自己署名ルートを削除します。証明書バンドルには、証明書の公開鍵と中間認証局の公開鍵のみを含める必要があります。ブラウザーは、トラストストアに既に存在するルートに解決される証明書のみを信頼し、証明書バンドルで送信されたルート証明書を無視します(それ以外の場合は、誰でも任意のルートを送信できます)。
これが本当であり、ルート証明書をサーバーにインストールする必要がない場合でも、サーバーの適切なセットアップと、チェーンがルートに検証される方法について私が知っていたと思います。次に、もう一度 この質問 を見ると、 Thomas Porninの回答 の「証明書と認証」セクションで、次のように述べています:
したがって、クライアントは次のことを行うことになっています。
- サーバーの証明書で終わる証明書チェーンを取得します。サーバーからの証明書メッセージには、このようなチェーンが含まれているはずです。
これは、私が何かを誤解していない限り、上記のSymantec/VeriSignメッセージとは正反対です。そう:
サーバーには、ルートを含む完全なチェーンをインストールする必要がありますか?そうでない場合、サーバーはハンドシェイク中にルート証明書を提供しないので、ブラウザは検証と比較するために何を使用しますか?それは単にアイデンティティ証明書を見て、そこから取得しますか? (ローカルマシンでID証明書を開いて、認証パスに完全なチェーンが表示されるようにしますか?)
ここでも、SSLライブラリを使用するスタンドアロンのクライアントアプリについてはどうでしょうか。信頼されたルートとブラウザのパス構築方法が異なる可能性があるため、これはアプリケーションに依存しますか?
サーバーは常にチェーンを送信します。 TLS標準 のとおり、チェーンにはルート証明書自体が含まれる場合と含まれない場合があります。クライアントはすでにルートを持っているので、そのルートは必要ありません。そして、確かに、クライアントがまだルートを持っていない場合、サーバーからルートを信頼してもすでにそこにいるだけで信頼できるため、ルートを信頼することはできません。
シマンテックは、ルートを送信せず、残りのチェーンのみを送信することを推奨していると述べています。これは理にかなっています。ルートは検証の目的には役に立たないので、ルートを送信せずに、接続ごとに1 kB程度のデータ帯域幅を節約することもできます。
とにかく:
サーバーの証明書とそのチェーンは、サーバー用ではありません。サーバーは独自の証明書を使用しません。証明書は常に他の人々(ここではクライアント)向けです。サーバーが使用するのは、その秘密鍵(証明書の公開鍵に対応する)です。特に、サーバーは自身の証明書またはそれを発行したCAをtrustする必要はありません。
TLSでは、サーバーはチェーンを送信することになっています。クライアントはどういうわけかハンドシェイクにサーバーの公開鍵を使用することになっています。クライアントは任意の方法でその公開鍵を自由に「知る」ことができますが、もちろんクライアントはサーバーが送信した証明書チェーンからサーバーの公開鍵を取得することが期待されます。ブラウザーは主に、サーバーによって送信されたチェーンを使用しようとします(ブラウザーによって既に信頼されているルートの1つの下にリンクしようとすることにより)。失敗した場合は、すでに知っているか、オンザフライでダウンロードできる中間CA証明書に基づいて他のチェーンを構築しようとします。
スタンドアロンアプリケーションでは、アプリケーション作成者は任意の方法でそのステップを自由に構成またはバイパスできます。これは、サーバーの公開鍵をアプリケーションコードでハードコーディングできる場合に役立ちます(この場合、サーバーから送信されたチェーンは完全に無視されます) )。残念ながら、カスタム証明書検証ステップを実装する自由は、セキュリティを強化し、それを刺して死に至らしめ、その死体を溝に投げ込む自由でもあります。それはあまりにも頻繁に起こります。
サーバーはハンドシェイク中にルート証明書を提供しないため、ブラウザーは検証のために何を比較するために使用しますか
証明書チェックの全体的な考え方は、クライアントが信頼するいくつかのルート証明書(ブラウザまたはOSに付属)を持ち、ブラウザがこのローカルトラストアンカーに対して送信する証明書を検証することです。
つまり、このルート証明書はすでにクライアント側にあるはずなので、サーバーはルート証明書をクライアントに送信する必要はありません(送信すべきではありません)。それでもルート証明書を送信する場合、クライアントは単にそれを破棄します。つまり、サーバーから送信されたルート証明書を信頼しません。
ここでも、SSLライブラリを使用するスタンドアロンのクライアントアプリについてはどうでしょうか。信頼されたルートとブラウザのパス構築方法が異なる可能性があるため、これはアプリケーションに依存しますか?
ブラウザとSSLライブラリ間の基本的な検証プロセスは同じです。 opensslとブラウザーのEdgeケースでのパス構築にはいくつかの違いがあります( http://rt.openssl.org/Ticket/Display.html?id=2732&user=guest&pass=guest を参照)と検証サーバー証明書の名前に対するターゲットのホスト名の比較は、多くの場合、バグがあるか、一般的なブラウザの外部には存在しません。
都合のよいときにルートを送信します。
クライアントがルートを信頼する場合、ルートを送信するかどうかに関係なく、ルートは信頼されます。
クライアントがルートを認識しない場合、私の経験では、MS Windowsクライアントは、信頼されていないルートがチェーンで提供された場合に、混乱の少ない診断メッセージを生成します。
ルートが提供されていない場合にどのルートを使用するかを知る方法については、次のルート(提供されたチェーンに含まれている必要があります)にルートの識別情報が含まれています。クライアントはこのルートを使用してルートを検索します。クライアントのストア。
ルートCAがキーストアに含まれていない場合、起動しないのサーバーソフトウェア(IBM HTTP Serverなど)があることを考慮してください。