[解決済み] SSLHandshakeExceptionによるhandshake_failureという致命的なアラートを受信しました。
質問
オーソライズドSSL接続に問題があります。Client Authorized SSL証明書を使用して外部サーバーに接続するStrutsアクションを作成しました。このアクションで、銀行のサーバーにデータを送信しようとしているのですが、サーバーから次のようなエラーが表示され、うまくいきません。
error: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
サーバーにデータを送信する Action クラスのメソッド
//Getting external IP from host
URL whatismyip = new URL("http://automation.whatismyip.com/n09230945.asp");
BufferedReader inIP = new BufferedReader(new InputStreamReader(whatismyip.openStream()));
String IPStr = inIP.readLine(); //IP as a String
Merchant merchant;
System.out.println("amount: " + amount + ", currency: " + currency + ", clientIp: " + IPStr + ", description: " + description);
try {
merchant = new Merchant(context.getRealPath("/") + "merchant.properties");
} catch (ConfigurationException e) {
Logger.getLogger(HomeAction.class.getName()).log(Level.INFO, "message", e);
System.err.println("error: " + e.getMessage());
return ERROR;
}
String result = merchant.sendTransData(amount, currency, IPStr, description);
System.out.println("result: " + result);
return SUCCESS;
私のmerchant.propertiesファイルです。
bank.server.url=https://-servernameandport-/
https.cipher=-cipher-
keystore.file=-key-.jks
keystore.type=JKS
keystore.password=-password-
ecomm.server.version=2.0
encoding.source=UTF-8
encoding.native=UTF-8
初めてこれは証明書の問題だと思い、.pfxから.jksに変換しましたが、何の変化もなく同じエラーが出ます。
解決方法は?
様々な原因でハンドシェイクに失敗した可能性があります。
- クライアントとサーバーで使用されている暗号スイートの互換性がない。この場合、クライアントはサーバーがサポートする暗号スイートを使用する(または有効にする)必要があります。
- 使用しているSSLのバージョンに互換性がない(サーバーはTLS v1しか受け付けないが、クライアントはSSL v3しか使用できない可能性がある)。この場合も、クライアントはSSL/TLSプロトコルの互換性のあるバージョンを使用するようにしなければならないかもしれません。
- サーバー証明書のトラストパスが不完全で、サーバーの証明書がクライアントから信頼されていない可能性があります。これは通常、より冗長なエラーになりますが、十分にあり得ることです。通常は、サーバーのCA証明書をクライアントのトラストストアにインポートすることで修正します。
- 別のドメインで発行された証明書である。この場合も、もっと冗長なメッセージになるはずですが、これが原因である場合に備えて、ここで修正方法を明記しておきます。この場合の解決策は、サーバー(あなたのものではないようです)に正しい証明書を使用させることでしょう。
根本的な故障は特定できないので、このような場合は
-Djavax.net.debug=all
フラグを使用して、確立された SSL 接続のデバッグを有効にします。デバッグをオンにすると、ハンドシェイクのどのアクティビティが失敗したかをピンポイントで特定することができます。
更新情報
現在公開されている情報によると、この問題は、サーバーに発行された証明書とルートCAとの間の証明書信頼パスが不完全であることが原因であるように思われます。多くの場合、ルート認証局の証明書がトラストストアに存在しないため、証明書のトラストパスが存在せず、証明書がクライアントから本質的に信頼されない状況になります。ブラウザは警告を表示してユーザーがこれを無視できるようにすることができますが、同じことはSSLクライアント(たとえば HttpsURLConnection クラス、または Apache のような HTTP クライアントライブラリ HttpComponents クライアント ).
これらのクライアントクラス/ライブラリのほとんどは、証明書の検証のためにJVMによって使用されるトラストストアに依存することになります。ほとんどの場合、これは
cacerts
ファイル(JRE_HOME/lib/security ディレクトリ)にあります。もし、トラストストアの場所がJVMシステムプロパティである
javax.net.ssl.trustStore
そのパスのストアは、通常、クライアント・ライブラリで使用されるものです。もし疑問があれば、あなたの
Merchant
クラスが接続に使用しているクラス/ライブラリーを特定します。
このトラストストアにサーバーの証明書発行局を追加することで、問題は解決するはずです。私の 関連する質問で、ツールの入手方法について回答しています。 この目的のために Java キートゥールユーティリティ で十分である。
警告 : トラストストアは、基本的に、あなたが信頼するすべてのCAのリストです。もし、あなたが信頼していないCAに属していない証明書を入れた場合、その実体が発行した証明書を持つサイトへのSSL/TLS接続は、秘密鍵が利用可能であれば復号化することが可能です。
更新その2:JSSEトレースの出力を理解する
JVMが使用するキーストアとトラストストアは、通常、以下のような感じで、一番最初にリストアップされます。
keyStore is :
keyStore type is : jks
keyStore provider is :
init keystore
init keymanager of type SunX509
trustStore is: C:\Java\jdk1.6.0_21\jre\lib\security\cacerts
trustStore type is : jks
trustStore provider is :
間違ったトラストストアが使用されている場合、サーバーの証明書を正しいものに再インポートするか、リストされたものを使用するようにサーバーを再設定する必要があります(複数のJVMがあり、それらのすべてが異なるニーズに使用されている場合は推奨されません)。
信頼する証明書のリストに必要な証明書が含まれているかどうかを確認したい場合、同じセクションがあり、次のように始まります。
adding as trusted cert:
Subject: CN=blah, O=blah, C=blah
Issuer: CN=biggerblah, O=biggerblah, C=biggerblah
Algorithm: RSA; Serial number: yadda
Valid from SomeDate until SomeDate
サーバーのCAが主語かどうかを調べる必要があります。
ハンドシェイクのプロセスには、いくつかの重要なエントリーがあります (それらを詳しく理解するには SSL を知る必要がありますが、今回の問題をデバッグする目的では、通常 ServerHello で handshake_failure が報告されることを知っていれば十分でしょう)。
1. クライアントハロー
接続が初期化される際に、一連のエントリーが報告されます。SSL/TLS 接続のセットアップでクライアントから送られる最初のメッセージは ClientHello メッセージで、通常次のようにログに報告されます。
*** ClientHello, TLSv1
RandomCookie: GMT: 1291302508 bytes = { some byte array }
Session ID: {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA]
Compression Methods: { 0 }
***
使用されている暗号スイートにも注目してください。これは は同意しなければならないかもしれません 銀行のライブラリでも同じ規約が採用されている可能性があるため、merchant.properties ファイル内のエントリと一致させます。使用されている規約が異なっていても、心配はいりません。暗号スイートに互換性がない場合は、ServerHello にその旨が表示されます。
2. サーバーハロー
サーバーはServerHelloで応答し、接続のセットアップを続行できるかどうかが示されます。ログのエントリーは通常、以下のようなものです。
*** ServerHello, TLSv1
RandomCookie: GMT: 1291302499 bytes = { some byte array}
Cipher Suite: SSL_RSA_WITH_RC4_128_SHA
Compression Method: 0
***
これは、サーバとクライアントの両方が利用できる最良の暗号スイートである。通常、暗号スイートはエラーが発生した場合、指定されない。サーバーの証明書(およびオプションでチェーン全体)はサーバーから送信され、次のようなエントリで見つけることができます。
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: CN=server, O=server's org, L=server's location, ST =Server's state, C=Server's country
Signature Algorithm: SHA1withRSA, OID = some identifer
.... the rest of the certificate
***
証明書の検証が成功した場合、次のようなエントリが表示されます。
Found trusted certificate:
[
[
Version: V1
Subject: OU=Server's CA, O="Server's CA's company name", C=CA's country
Signature Algorithm: SHA1withRSA, OID = some identifier
上記のいずれかのステップが成功しなかったために handshake_failure が発生し、この段階でハンドシェイクは通常完了します (実際には、ハンドシェイクの後続ステージでは通常ハンドシェイクの失敗は発生しません)。どの段階が失敗したかを把握し、適切なメッセージを質問に対する更新として投稿する必要があります(メッセージをすでに理解し、それを解決するために何をすべきかを知っている場合を除く)。
関連
-
[解決済み] JVMフラグCMSClassUnloadingEnabledは、実際に何をするのですか?
-
[解決済み] Java の substring() の時間複雑性
-
[解決済み] コレクションへの共有参照が見つかりました org.hibernate.HibernateException
-
[解決済み] なぜJPAには@Transientアノテーションがあるのですか?
-
[解決済み] android.support.v4.app.FragmentActivity' で 'TAG' がプライベートアクセスされている。
-
[解決済み] Java Swingで複数のボタンに対して複数のActionListenersを追加する方法
-
[解決済み] java.util.MissingFormatArgumentException: 形式指定子 '%s' がありません。
-
[解決済み] スリーピング中のスレッドが割り込まれ、データベースへの接続が失われる
-
[解決済み] タイプの安全性。アンチェック・キャスト
-
[解決済み] コレクションを反復処理し、ループ内でオブジェクトを削除する際に ConcurrentModificationException を回避する。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] java.sql.SQLException: ORA-00933: SQL コマンドが正しく終了していません。
-
[解決済み] パラメータ[変数]の不正な修飾子;finalのみが許可される[closed]。
-
[解決済み] Cloneable throws CloneNotSupportedException
-
[解決済み] 1行目2列目でBEGIN_ARRAYを期待したが、BEGIN_OBJECTだった。
-
[解決済み] JavaにおけるMouseListenerとMouseAdapterの違いについて
-
[解決済み] ファイルを作成せずに、ファイルが存在するかどうかをチェックする
-
[解決済み] アニメーションGIFの表示
-
[解決済み] javaでメソッドを呼び出すプログラムのエラー修正
-
[解決済み] Java: getInstanceとStaticの比較
-
[解決済み] IntegerからBigIntegerへの変換