安全なWebサービスに接続しようとしています。
キーストアとトラストストアが正しく設定されていても、ハンドシェイクに失敗していました。
数日間のフラストレーション、果てしないグーグル、周りの皆への質問の後、唯一の問題はJavaがハンドシェーク中にクライアント証明書をサーバーに送信しないことを選んだことでした。
具体的には:
私の質問:
私はなんとかこのための汚い回避策をまとめましたが、私はそれについてあまり満足していないので、誰かが私のためにこれを明確にすることができればうれしいです。
クライアント証明書とその秘密鍵があるエントリに関連付けずに、中間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
ここに追加すると、%> openssl s_client -connect Host.example.com:443を使用してダンプを確認し、すべてのメイン証明書を確認できますクライアントに対して有効です。出力の下部でこれを探しています。 戻りコードの確認:0(ok)
-showcertsを追加すると、ホスト証明書とともに送信されたキーチェーンのすべての情報がダンプされます。これは、キーチェーンにロードしたものです。