收到致命警报:handshake_failure通过SSLHandshakeException [英] Received fatal alert: handshake_failure through SSLHandshakeException

查看:185
本文介绍了收到致命警报:handshake_failure通过SSLHandshakeException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到授权SSL连接的问题。我创建了Struts Action,它通过Client Authorized SSL证书连接到外部服务器。在我的行动中我试图将一些数据发送到银行服务器,但没有任何运气,因为我从服务器得到以下错误:

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

我的方法从我的Action类发送数据到服务器

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;

我的merchant.properties文件:

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

我第一次认为这是证书问题,我将它从.pfx转换为.jks,但我有相同的错误,没有任何更改。

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.

推荐答案

握手失败可能有由于各种原因发生:

The handshake failure could have occurred due to various reasons:


  • 客户端和服务器使用的密码套件不兼容。这将要求客户端使用(或启用)服务器支持的密码套件。

  • 使用的SSL版本不兼容(服务器可能只接受TLS v1,而客户端只能使用SSL v3)。同样,客户端可能必须确保它使用兼容版本的SSL / TLS协议。

  • 服务器证书的信任路径不完整;客户端可能不信任服务器的证书。这通常会导致更详细的错误,但很有可能。通常,修复方法是将服务器的CA证书导入客户端的信任存储区。

  • 为不同的域颁发证书。同样,这会导致更详细的消息,但我会在此处说明修复,以防这是原因。在这种情况下的解决方案是获取服务器(它似乎不是你的)使用正确的证书。

  • 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.

因为,无法确定潜在的故障,最好打开 -Djavax.net.debug = all 标志,用于启用已建立的SSL连接的调试。打开调试后,您可以查明握手中的哪些活动失败。

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.

更新

根据现有的详细信息,问题似乎是由于颁发给服务器的证书与根CA之间的证书信任路径不完整。在大多数情况下,这是因为信任库中没有根CA的证书,导致证书信任路径不存在的情况;证书基本上不受客户的信任。浏览器可以发出警告,以便用户可以忽略这一点,但SSL客户端的情况并非如此(例如 HttpsURLConnection 类,或任何HTTP客户端库,如Apache HttpComponents客户端)。

Based on the details now available, it appears that the problem is due to an incomplete certificate trust path between the certificate issued to the server, and a root CA. In most cases, this is because the root CA's certificate is absent in the trust store, leading to the situation where a certificate trust path cannot exist; the certificate is essentially untrusted by the client. Browsers can present a warning so that users may ignore this, but the same is not the case for SSL clients (like the HttpsURLConnection class, or any HTTP Client library like Apache HttpComponents Client).

大多数这些客户端类/库都依赖于JVM用于证书的信任存储验证。在大多数情况下,这将是JRE_HOME / lib / security目录中的 cacerts 文件。如果已使用JVM系统属性 javax.net.ssl.trustStore 指定了信任库的位置,则该路径中的存储通常是客户端使用的存储图书馆。如果您有疑问,请查看您的商家类,并找出用于建立连接的类/库。

Most these client classes/libraries would rely on the trust store used by the JVM for certificate validation. In most cases, this will be the cacerts file in the JRE_HOME/lib/security directory. If the location of the trust store has been specified using the JVM system property javax.net.ssl.trustStore, then the store in that path is usually the one used by the client library. If you are in doubt, take a look at your Merchant class, and figure out the class/library it is using to make the connection.

将服务器的证书颁发CA添加到此信任库应该可以解决问题。您可以参考我的关于获取工具的相关问题的答案,但是 Java keytool实用程序足以实现此目的。

Adding the server's certificate issuing CA to this trust store ought to resolve the problem. You can refer to my answer on a related question on getting tools for this purpose, but the Java keytool utility is sufficient for this purpose.

警告 :信任存储本质上是您信任的所有CA的列表。如果您输入的证书不属于您不信任的CA,则如果私钥可用,则可以解密具有该实体颁发的证书的站点的SSL / TLS连接。

Warning: The trust store is essentially the list of all CAs that you trust. If you put in an certificate that does not belong to a CA that you do not trust, then SSL/TLS connections to sites having certificates issued by that entity can be decrypted if the private key is available.

更新#2:了解JSSE跟踪的输出

JVM使用的密钥库和信任库是通常在最开始列出,有点像以下内容:

The keystore and the truststores used by the JVM are usually listed at the very beginning, somewhat like the following:

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 : 

如果错误使用truststore,然后您需要将服务器的证书重新导入到正确的服务器,或者重新配置服务器以使用列出的服务器(如果您有多个JVM,则不建议使用它们,并且所有这些都是用于不同的需求)。

If the wrong truststore is used, then you'll need to re-import the server's certificate to the right one, or reconfigure the server to use the one listed (not recommended if you have multiple JVMs, and all of them are used for different needs).

如果要验证信任证书列表是否包含所需的证书,那么有一个相同的部分,其开头为:

If you want to verify if the list of trust certs contains the required certs, then there is a section for the same, that starts as:

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是一个主题。

You'll need to look for if the server's CA is a subject.

握手过程将有一些显着的条目(你需要知道SSL以详细了解它们,但是为了调试当前问题,只需知道在ServersHello中通常会报告handshake_failure。

The handshake process will have a few salient entries (you'll need to know SSL to understand them in detail, but for the purpose of debugging the current problem, it will suffice to know that a handshake_failure is usually reported in the ServerHello.

1. ClientHello

初始化连接时将报告一系列条目。客户端在SSL / TLS连接设置中发送的第一条消息是ClientHello消息,通常在日志中报告为:

A series of entries will be reported when the connection is being initialized. The first message sent by the client in a SSL/TLS connection setup is the ClientHello message, usually reported in the logs as:

*** 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将说明。

Note the cipher suites used. This might have to agree 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

服务器以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

上面的一个步骤不会成功,导致handshake_failure,因为握手通常在这个阶段完成(不是真的,但是s后续的握手阶段通常不会导致握手失败。您需要确定哪个步骤失败,并将相应的消息发布为问题的更新(除非您已经理解了该消息,并且您知道如何解决该消息)。

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).

这篇关于收到致命警报:handshake_failure通过SSLHandshakeException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆