首页 > 解决方案 > Java 7:发送 TLSv1.2 警报:致命,描述 = handshake_failure mule

问题描述

我正在使用java 7mule 3.7.0,我已经安装了Java Cryptography Extension

我正在尝试向服务器发送请求,但我得到:

java.io.EOFException: SSL peer shut down incorrectly
        at sun.security.ssl.InputRecord.read(InputRecord.java:482)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:944)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1342)


Cipher Suites: [TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, secp384r1, secp521r1}
Extension ec_point_formats, formats: [uncompressed]
Extension extended_master_secret
Extension server_name, server_name: [host_name: merchant.payb.lv]
***
entry.worker.04, WRITE: TLSv1 Handshake, length = 136
entry.worker.04, received EOFException: error
entry.worker.04, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
entry.worker.04, SEND TLSv1.2 ALERT:  fatal, description = handshake_failure
entry.worker.04, WRITE: TLSv1.2 Alert, length = 2
entry.worker.04, Exception sending alert: java.net.SocketException: Broken pipe (Write failed)
entry.worker.04, called closeSocket()
entry.worker.04, called close()
entry.worker.04, called closeInternal(true)
entry.worker.04, called close()
entry.worker.04, called closeInternal(true)
entry.worker.04, called close()
entry.worker.04, called closeInternal(true)

据我了解,问题是不支持TLSv1.2 ,但是在我安装Java Cryptography Extension之后应该有,有人可以帮忙吗?

我试过了:

System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2")
System.setProperty("jdk.tls.client.protocols", "TLSv1,TLSv1.1,TLSv1.2")
System.setProperty("https.cipherSuites", "TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA")

也试过:

String[] ciphers = new String[2]
ciphers[0] = "TLS_RSA_WITH_AES_256_CBC_SHA256"
ciphers[1] = "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"
SSLSocket.setEnabledCipherSuites(ciphers)

String[] protocols = new String[1]
protocols[0] = "TLSv1.2";
SSLSocket.setEnabledProtocols(protocols)

标签: javasslmuletls1.2

解决方案


我正在使用 java 7,mule 3.7.0,我已经安装了 Java Cryptography Extension

你不可能已经安装了 JCE。自 1.5 以来它已包含在 Java 构建中(相当于现在的 5)。您可能的意思是您安装了JCE Unlimited Strength Jurisdiction Policy Files(j8 的链接,因为 j7 现在已存档)。这些策略文件是包含JCE 策略文件—— 并且只需要 Oracle 以前的 Sun Java

您没有确切说明您使用的是哪个 Java 版本,但您的跟踪表明它是 OpenJDK 的 RedHat 系列构建。如果是这样,则不需要无限的策略文件并且无效;OpenJDK 创建于 2007 年,从未受制于上世纪为当时的 Sun Java 设计的“有限”加密政策。(在过去的几个月里,Oracle j8、j9 和 j10 也最终取消了大部分这个“功能”,用一个默认为 . 的可编辑文本项取而代之unlimited。)

据我了解,问题是不支持 TLSv1.2,但是在我安装 Java Cryptography Extension 之后应该有,

JCE 策略文件对 TLS 协议支持绝对没有影响。它们对 TLS 的唯一影响是启用使用 AES-256 的密码套件,这与协议不同且独立 - 如上所述,仅在(非最近的)Sun/Oracle 软件包中很重要。

Java 7 确实实现了开箱即用的 TLS 1.2,但所有免费(免费)Oracle 软件包(最高 7u80)都禁用了它,默认情况下在客户端禁用了 1.1。在免费版本的生命周期结束后,据报道,“高级”即付费支持版本确实在 7u131 启用了它们,我认为 OpenJDK 构建也是如此,但无法检查。

根据https://www.ssllabs.com/ssltest/analyze.html?d=merchant.payb.lv,该服务器实际上并不需要AES-256;它还接受甚至更喜欢AES-128 套件,并且即使在没有无限策略的情况下也适用于 Oracle j7 ,只要至少启用了 TLS 1.1。它实际上并不需要 1.2,但由于启用 1.1 或 1.2 的努力是相同的,您不妨选择 1.2。

我试过:
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2")
System.setProperty("jdk.tls.client.protocols", "TLSv1,TLSv1.1,TLSv1. 2")
System.setProperty("https.cipherSuites", "TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA")

https.protocols仅适用于使用HttpsURLConnection(不是直接使用 JSSE)的连接,我不知道 mule 是否这样做,无论是在一般情况下还是在您的系统上。jdk.tls.client.protocolsOracle j7 的免费版本不支持;它似乎已添加到 7u91 或可能 7u95 的付费版本中,并且可能与 OpenJDK 相同。https.cipherSuites也仅适用于HttpsURLConnection并且无论如何都不需要,因为默认密码套件适用于该服务器;此外,服务器不支持任何 3DES 套件——也不支持任何数据密码的 ECDH_RSA。(几乎没有人在任何地方使用 ECDH_RSA;包括此服务器在内的许多人都使用 ECDHE_RSA,是的,Ephemeral 的第二个 E 产生了非常大而重要的区别。)

还尝试过:
String[] ciphers = new String[2]
ciphers[0] = "TLS_RSA_WITH_AES_256_CBC_SHA256"
ciphers[1] = "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"
SSLSocket.setEnabledCipherSuites(ciphers)
String[] protocols = new String[1]
protocols[0] = “TLSv1.2”;
SSLSocket.setEnabledProtocols(协议)

这不可能。setEnabledCipherSuites并且setEnabledProtocols是非静态方法,必须在对象(实例)上调用,而不是在类上。您使用哪个对象至关重要。如上所述,密码套件根本不需要更改,而您尝试设置的第二个在两个方面都是错误的。

我无法重现你的踪迹。它为 ClientHello 记录WRITE: TLSv1 Handshake(意思是 1.0),但是您隐藏了可以确认它是否真的是 1.0 的数据。当我使用默认为 1.0 的 7u80(具有无限策略,并且没有骡子)进行测试时,它会像您一样获得 EOF,但随后会记录SEND TLSv1 ALERTWRITE: TLSv1 Alert-- NOT TLSv1.2。当我使用 7u80 测试并正确启用 1.2 时,它按预期成功连接。我与此证据一致的唯一理论是您没有正确启用 1.2篡改了日志。


推荐阅读