ようやくすべての問題を解決できたので、自分の質問に答えます。これらは、特定の問題を解決するために管理するために使用した設定/ファイルです。
クライアントのキーストアはあるPKCS#12形式の入ったファイル
- クライアントの公開証明書(この例では自己署名CAによって署名されています)
- クライアントの秘密鍵
これを生成するにpkcs12
は、たとえばOpenSSLのコマンドを使用しました。
openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name "Whatever"
ヒント:バージョン0.9.8h ではなく、最新のOpenSSLを入手してください。これは、PKCS#12ファイルを適切に生成できないバグの影響を受けているようです。
このPKCS#12ファイルは、サーバーがクライアントに認証を明示的に要求したときに、Javaクライアントがクライアント証明書をサーバーに提示するために使用します。クライアント証明書認証のプロトコルが実際に機能する方法の概要については、TLSに関するウィキペディアの記事を参照してください(ここでクライアントの秘密鍵が必要な理由についても説明しています)。
クライアントのトラストストアは簡単ですJKS形式の入ったファイルのルートまたは中間CA証明書を。これらのCA証明書は、通信を許可するエンドポイントを決定します。この場合、クライアントは、トラストストアのCAのいずれかによって署名された証明書を提示するサーバーに接続できます。
これを生成するには、たとえば、標準のJava keytoolを使用できます。
keytool -genkey -dname "cn=CLIENT" -alias truststorekey -keyalg RSA -keystore ./client-truststore.jks -keypass whatever -storepass whatever
keytool -import -keystore ./client-truststore.jks -file myca.crt -alias myca
このトラストストアを使用して、クライアントは、で識別されるCAによって署名された証明書を提示するすべてのサーバーとの完全なSSLハンドシェイクを実行しようとしますmyca.crt
。
上記のファイルはクライアント専用です。サーバーをセットアップする場合も、サーバーには独自のキーおよびトラストストアファイルが必要です。Javaクライアントとサーバー(Tomcatを使用)の両方で完全に機能する例を設定するための優れたウォークスルーは、このWebサイトにあります。
問題/備考/ヒント
- クライアント証明書認証は、サーバーによってのみ実施できます。
- (重要!)サーバーが(TLSハンドシェイクの一部として)クライアント証明書を要求すると、証明書要求の一部として信頼できるCAのリストも提供されます。あなたは認証のために存在したいクライアント証明書がされている場合ではないこれらのCAさんの1が署名し、(私の意見では、これは奇妙な動作ですが、私は確かにそれの理由がありますよ)すべてで発表されることはありません。これが私の問題の主な原因でした。なぜなら、相手が私の自己署名クライアント証明書を受け入れるようにサーバーを適切に構成しておらず、問題はリクエストでクライアント証明書を適切に提供していないためであると私たちは考えていました。
- Wiresharkを入手してください。SSL / HTTPSパケット分析が優れており、問題のデバッグと発見に非常に役立ちます。これ
-Djavax.net.debug=ssl
は、Java SSLデバッグ出力に不満がある場合に似ていますが、より構造化されており、(おそらく)解釈が容易です。
Apache httpclientライブラリを使用することは完全に可能です。httpclientを使用する場合は、宛先URLを同等のHTTPSで置き換え、次のJVM引数を追加します(他のクライアントでも同じです。HTTP/ HTTPSを介したデータの送受信に使用するライブラリに関係ありません)。 :
-Djavax.net.debug=ssl
-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.keyStore=client.p12
-Djavax.net.ssl.keyStorePassword=whatever
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.trustStore=client-truststore.jks
-Djavax.net.ssl.trustStorePassword=whatever