web-dev-qa-db-ja.com

なぜJava SSLハンドシェイク中にクライアント証明書を送信しないのですか?

安全なWebサービスに接続しようとしています。

キーストアとトラストストアが正しく設定されていても、ハンドシェイクに失敗していました。

数日間のフラストレーション、果てしないグーグル、周りの皆への質問の後、唯一の問題はJavaがハンドシェーク中にクライアント証明書をサーバーに送信しないことを選んだことでした。

具体的には:

  1. サーバーがクライアント証明書を要求しました(CN = RootCA)-つまり、「ルートCAによって署名された証明書をください」
  2. Javaはキーストアを調べて、「SubCA」によって署名されたクライアント証明書のみを検出し、「SubCA」は「RootCA」によって発行されます。トラストストアを調べる必要はありませんでした...
  3. 悲しいことに、「SubCA」証明書をキーストアに追加しようとしても、まったく役に立ちませんでした。証明書がキ​​ーストアにロードされるかどうかを確認しました。ただし、KeyManagerはクライアント証明書を除くすべての証明書を無視します。
  4. 上記のすべてにより、Javaはサーバーの要求を満たす証明書を持たず、何も送信しないと判断する... tadaaaハンドシェークの失敗:-(

私の質問:

  1. 「証明書チェーンを破る」などの方法で「SubCA」証明書をキーストアに追加して、KeyManagerがクライアント証明書のみをロードし、残りを無視することは可能ですか? (Chromeとopensslはそれを把握しているので、なぜjavaにできないのですか?-「SubCA」証明書は常に信頼できる機関として常に提示されるため、Chromeは、ハンドシェイク中のクライアント証明書)
  2. これはサーバー側の正式な「構成の問題」ですか?サーバーはサードパーティです。サーバーが「SubCA」機関によって署名された証明書を要求することを期待します。それは彼らが私たちに提供したものだからです。これがChromeとopensslで機能するという事実は、それらが「制限が少なく」、Javaが「本によって」失敗して失敗するためです。

私はなんとかこのための汚い回避策をまとめましたが、私はそれについてあまり満足していないので、誰かが私のためにこれを明確にすることができればうれしいです。

61
Jakub Hlavatý

クライアント証明書とその秘密鍵があるエントリに関連付けずに、中間CA証明書をキーストアにインポートした可能性があります。 keytool -v -list -keystore store.jksを使用してこれを確認できるはずです。エイリアスエントリごとに1つの証明書しか取得しない場合、それらは一緒ではありません。

証明書とそのチェーンを、プライベートキーを持つキーストアエイリアスに一緒にインポートする必要があります。

どのキーストアエイリアスに秘密キーがあるかを調べるには、keytool -list -keystore store.jksを使用します(ここではJKSストアタイプを想定しています)。これにより、次のようなことがわかります。

Your keystore contains 1 entry

myalias, Feb 15, 2012, PrivateKeyEntry, 
Certificate fingerprint (MD5): xxxxxxxx

ここで、エイリアスはmyaliasです。これに加えて-vを使用すると、Alias Name: myaliasが表示されます。

まだ個別に持っていない場合は、キーストアからクライアント証明書をエクスポートします。

keytool -exportcert -rfc -file clientcert.pem -keystore store.jks -alias myalias

これにより、PEMファイルが得られます。

テキストエディター(またはcat)を使用して、そのクライアント証明書と中間CA証明書(および必要に応じてルートCA証明書自体)でファイルを準備します(bundle.pemと呼びます)。クライアント証明書は最初にあり、発行者証明書はすぐ下にあります。

これは次のようになります。

-----BEGIN CERTIFICATE-----
MIICajCCAdOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVSzEa
....
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICkjCCAfugAwIBAgIJAKm5bDEMxZd7MA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV
....
-----END CERTIFICATE-----

次に、このバンドルをプライベートキーがあるエイリアスにインポートします。

keytool -importcert -keystore store.jks -alias myalias -file bundle.pem
91
Bruno

ここに追加すると、%> openssl s_client -connect Host.example.com:443を使用してダンプを確認し、すべてのメイン証明書を確認できますクライアントに対して有効です。出力の下部でこれを探しています。 戻りコードの確認:0(ok)

-showcertsを追加すると、ホスト証明書とともに送信されたキーチェーンのすべての情報がダンプされます。これは、キーチェーンにロードしたものです。

5
tls