2012-02-15 12 views
49

セキュリティで保護されたWebサービスに接続しようとしています。SSLハンドシェイク中にjavaがクライアント証明書を送信しないのはなぜですか?

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

数日間の不満の後、無限のグーグルと私は周囲の人に尋ねましたが、唯一の問題は、Javaがハンドシェイク中にサーバーにクライアント証明書を送信しないことを選択したことでした。

具体的に:

  1. Serverは、クライアント証明書(CN = ROOTCAのCA)を要求した - すなわち、「私のルートCAによって署名された証明書を与える」
  2. をJavaがキーストアに見て、唯一の私のクライアントが発見しました「SubCA」によって署名され、「RootCA」によって発行される証明書。それはトラストストアを調べるのに気にしなかった...だから私はそう思うよ
  3. 悲しいことに、「SubCA」証明書をキーストアに追加しようとしたとき、それはまったく役に立たなかった。証明書がキ​​ーストアにロードされるかどうかを確認しました。これらは実行されますが、KeyManagerはクライアント以外のすべての証明書を無視します。
  4. Javaは、サーバーの要求を満たすすべての証明書を持っていないことを決定し

私の質問:-(何も... tadaaaハンドシェイクの失敗を送信しているという事実に上記リードのすべて:

  1. 「証明書チェーンを壊した」などの方法で「SubCA」証明書をキーストアに追加した可能性はありますか?KeyManagerはクライアント証明書のみを読み込み、残りは無視します(ChromeとopensslはそれでなぜJavaは使えないのですか? - 「SubCA」証明書は常に信頼できる権限として別々に表示されるので、Chrome appare正しくハンドシェイク中にクライアント証明書と一緒にパックします)
  2. これは正式な「設定上の問題」ですか?サーバーは第三者です。私はサーバーが、彼らが私たちに提供したものであるので、 "SubCA"権限によって署名された証明書を要求することを期待します。私はクロムとopensslで動作するという事実は、「あまり制限されていない」ためであり、Javaは「本によって」移動して失敗するためだと思う。

私はこれのために汚れた回避策を組み込むことができましたが、私はそれについて非常に幸せではないので、誰かが私のためにこれを明確にすることができたらうれしいです。

+2

@ Brunoの回答には、プライベートキーがあり、対応する証明書(つまり、同じエイリアス)がないという理由が追加されました。これにより、Javaは 'CertificateRequest'メッセージで尋ねられたときにJavaを送信できませんでした。その他の理由としては、サーバーが指定した発行者によって署名された証明書がないか、またはサーバーが指定した暗号と一致する証明書がないことがあります。 – EJP

+0

この問題は、サーバーで指定された暗号と一致するだけで解決しました。この情報をお寄せいただきありがとうございました。非常に便利でした。 –

答えて

76

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

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

秘密鍵を持つキーストアエイリアスを調べるには、keytool -list -keystore store.jks(ここではJKSストアタイプと仮定しています)を使用します。 、別名はmyaliasです。ここ

Your keystore contains 1 entry 

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

:これはあなたにこのような何かを教えてくれます。これに加えて-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 
+1

高貴な100万人のブルーノ - それは仕事をしました。私はこれがもう少し文書化されるかもしれないと思う。私はちょうど地獄が何が起こっているのか理解しようと数日間過ごした。 Javaのヒントは事実上存在しませんでした。 –

+1

私はあまりにも証明書と秘密鍵をインポートに組み合わせる必要がありますが、私は* .pem証明書ファイル( "----- BEGIN CERTIFICATE -----"で始まります)と* .key秘密鍵( "----- BEGIN RSAプライベート鍵-----")。私はそれらを連結してインポートしようとしましたが、私は得ました:keytool error:java.lang.Exception:X.509証明書ではありません。私が間違っているアイデアは?私はキーの種類pkcs12に変換する必要があるhttp://stackoverflow.com/questions/5297867/ssl-tomcat-certificate-error/11984173#11984173を読んでいます。何か案は?私は立ち往生している!ありがとうございました。 –

+0

ありがとうブルーノ、あなたは私の日を救った! – Gaucho

5

、あなたは%を使用することができます> openssl s_client -connect host.example.com:443とダンプを参照し、すべてのメイン証明書がクライアントに対して有効であることを確認します。これは出力の一番下にあります。 0(OK)

あなたは-showcertsを追加する場合、それはあなたがあなたのキーチェーンにロードされたものですホスト証明書と一緒に送られたキーチェーンのすべての情報をダンプします: は、リターンコードを確認してください。

+0

どのコマンドに '-showcerts'を使用しましたか? –

+0

@JerylCook 'openssl s_client -showcerts -connect host.example.com:443' – Sky

関連する問題