Received fatal alert: handshake_failure through SSLHandshakeException Ask Question

Received fatal alert: handshake_failure through SSLHandshakeException Ask Question

I have a problem with authorized SSL connection. I have created Struts Action that connects to external server with Client Authorized SSL certificate. In my Action I am trying to send some data to bank server but without any luck, because I have as a result from server the following error:

error: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

My Method from my Action class that sends data to server

//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;

My merchant.properties file:

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

For the first time I thought this is a certificate problem, I converted it from .pfx to .jks, but I have the same error, with no changes.

ベストアンサー1

The handshake failure could have occurred due to various reasons:

  • Incompatible cipher suites in use by the client and the server. This would require the client to use (or enable) a cipher suite that is supported by the server.
  • Incompatible versions of SSL in use (the server might accept only TLS v1, while the client is capable of only using SSL v3). Again, the client might have to ensure that it uses a compatible version of the SSL/TLS protocol.
  • Incomplete trust path for the server certificate; the server's certificate is probably not trusted by the client. This would usually result in a more verbose error, but it is quite possible. Usually the fix is to import the server's CA certificate into the client's trust store.
  • The cerificate is issued for a different domain. Again, this would have resulted in a more verbose message, but I'll state the fix here in case this is the cause. The resolution in this case would be get the server (it does not appear to be yours) to use the correct certificate.

Since, the underlying failure cannot be pinpointed, it is better to switch on the -Djavax.net.debug=all flag to enable debugging of the SSL connection established. With the debug switched on, you can pinpoint what activity in the handshake has failed.

Update

現在入手可能な詳細に基づくと、この問題は、サーバーに発行された証明書とルート CA 間の証明書信頼パスが不完全であることが原因であると思われます。ほとんどの場合、これはルート CA の証明書が信頼ストアに存在せず、証明書信頼パスが存在できない状況に陥っているためです。つまり、証明書はクライアントによって本質的に信頼されていないということです。ブラウザはユーザーがこれを無視できるように警告を表示できますが、SSL クライアント (HTTPSURL接続クラス、またはApacheのようなHTTPクライアントライブラリHttpComponents クライアント)。

これらのクライアント クラス/ライブラリのほとんどは、証明書の検証に JVM が使用するトラスト ストアに依存します。ほとんどの場合、これはcacertsJRE_HOME/lib/security ディレクトリ内のファイルになります。トラスト ストアの場所が JVM システム プロパティを使用して指定されている場合javax.net.ssl.trustStore、そのパス内のストアは通常、クライアント ライブラリによって使用されるストアです。不明な場合は、Merchantクラスを調べて、接続に使用されているクラス/ライブラリを調べてください。

サーバーの証明書発行CAをこの信頼ストアに追加すれば問題は解決するはずです。ツールの入手に関する関連質問への回答この目的のために、しかし、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 の知識が必要ですが、現在の問題をデバッグするには、handshake_failure が通常 ServerHello で報告されることを知っていれば十分です)。

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 }
***

使用されている暗号スイートに注意してください。同意しなければならないかもしれない with the entry in your merchant.properties file, for the same convention might be employed by the bank's library. If the convention used is different, there is no cause of worry, for the ServerHello will state so, if the cipher suite is incompatible.

2. ServerHello

The server responds with a ServerHello, that will indicate if the connection setup can proceed. Entries in the logs are usually of the following type:

*** ServerHello, TLSv1
RandomCookie:  GMT: 1291302499 bytes = { some byte array}
Cipher Suite: SSL_RSA_WITH_RC4_128_SHA
Compression Method: 0
***

Note the cipher suite that it has chosen; this is best suite available to both the server and the client. Usually the cipher suite is not specified if there is an error. The certificate of the server (and optionally the entire chain) is sent by the server, and would be found in the entries as:

*** 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
***

If the verification of the certificate has succeeded, you'll find an entry similar to:

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

One of the above steps would not have succeeded, resulting in the handshake_failure, for the handshake is typically complete at this stage (not really, but the subsequent stages of the handshake typically do not cause a handshake failure). You'll need to figure out which step has failed, and post the appropriate message as an update to the question (unless you've already understood the message, and you know what to do to resolve it).

おすすめ記事