带有 TLSv1.2 的 Java 7 连接到 LDAPS 握手失败
Posted
技术标签:
【中文标题】带有 TLSv1.2 的 Java 7 连接到 LDAPS 握手失败【英文标题】:Java 7 with TLSv1.2 connect to LDAPS handshake failure 【发布时间】:2018-09-19 17:55:59 【问题描述】:目前我使用的是 Java 7,但无法连接到 LDAPS。我尝试使用下面的代码,但仍然无法连接:
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
ctx.init(null, null, null);
SSLContext.setDefault(ctx);
以下是我从程序中得到的错误:
2018-04-10 15:21:23,446 INFO [stdout](EJB 默认 - 1)EJB 默认 - 1,写入:TLSv1.2 握手,长度 = 221
2018-04-10 15:21:23,446 INFO [stdout](EJB 默认 - 1)EJB 默认 - 1,阅读:TLSv1.2 警报,长度 = 2
2018-04-10 15:21:23,446 INFO [stdout](EJB 默认 - 1)EJB 默认 - 1,RECV TLSv1 ALERT:致命,handshake_failure
2018-04-10 15:21:23,446 INFO [stdout](EJB 默认 - 1)EJB 默认 - 1,称为 closeSocket()
2018-04-10 15:21:23,446 INFO [stdout](EJB 默认 - 1)EJB 默认 - 1,处理异常:javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure
之后我尝试运行协议测试来检查支持的协议:
Supported Protocols: 5
SSLv2Hello
SSLv3
TLSv1
TLSv1.1
TLSv1.2
Enabled Protocols: 1
TLSv1
我在java.security
中添加了以下行来禁用 TLSv1 并启用 TLSv1.2:
jdk.tls.disabledAlgorithms= SSLv3, SSLv2Hello, TLSv1, TLSv1.1
然后再次运行协议测试,结果是:
Supported Protocols: 5
SSLv2Hello
SSLv3
TLSv1
TLSv1.1
TLSv1.2
Enabled Protocols: 0
我已确认我的 LDAPS 服务器受支持并使用 TLSv1.2。我还在 Java 控制面板中启用了 TLS1.2,因为每当我尝试使用 TLSv1 时,它都会导致 protocol_version
错误
我的问题是:
RECV TLSv1 ALERT: fatal, handshake_failure
是什么?
如何在支持的协议中启用 TLSv1.2?
编辑 Java 7 或 8 是否支持密码套件:ECDHE-ECDSA-AES256-GCM-SHA384
?
我使用的是 Java 1.7_80。
【问题讨论】:
呃,你试图通过禁用其他的来启用 1.2?jdk.tls.client.protocols="TLSv1.2"
和禁用其他人呢?注意,支持 TLS 1.2 和支持 ECDSA 意味着支持两者的结合;密码套件需要实现,它们不会神奇地组合在一起。
另外:检查服务器的访问日志;并非所有详细信息都可能在 TLS 错误消息中返回。
在我的程序启动脚本中添加了 jdk.tls.client.protocols="TLSv1.2" 但仍然无法正常工作
【参考方案1】:
什么是 RECV TLSv1 ALERT:致命,握手失败?
这意味着我们(在 Java SSL/TLS 代码中,JSSE 中)收到了来自服务器的警报,其严重性为致命并键入 handshake_failure。由于它在发送一条握手消息后立即发生,如果您没有从您发布的日志摘录中省略其他相关信息,我们可能会收到此警报以响应 ClientHello 消息,这是发送的第一条握手消息。
此处的“TLSv1”可能具有误导性。它是SSLSocketImpl
对象中的一个变量,它被初始化为 TLSv1,并且在握手完成之前不会更新,因此此时它不能准确地指示正在使用的协议版本。 preceding 日志条目,“READ: TLSv1.2 Alert, length = 2”确实显示收到的实际版本并确认服务器至少尝试执行 TLS1.2 .
导致握手失败的原因是什么?很多很多的事情。从这个警报中几乎不可能判断出问题所在。
您最好的选择是查看服务器日志并找出为什么它说它发送了警报。
您最糟糕的选择是查看我们发送的 ClientHello - 其中大部分应该在您发布的行之前由 JSSE 记录 - 并考虑其中的所有内容,或者不在那里,服务器可能不喜欢其价值或缺席,并尝试更改它们中的每一个。有些比较容易更改,有些则非常困难,因此可能需要数小时到数周的时间。
如果您有任何其他客户端成功连接到同一台服务器,一个中间选项是查看 ClientHello 中有效的和无效的之间的差异,并考虑那些。作为这种情况的一种情况,如果您拥有或获得 OpenSSL,命令行 openssl s_client
可以快速且相当简单地用于测试 SSL/TLS 握手的一些变体,但不是所有变体。
你可能猜到我推荐第一个。
如何在支持的协议中启用 TLSv1.2?
您不需要在支持中启用它;您需要在 enabled 协议中启用它,并且您已经这样做了。使用SSLContext.getInstance("TLSv1.2")
是一种方法。在 Java 8 但不是(编辑)7 的免费 Oracle 更新中,使用 sysprop jdk.tls.client.protocols
是另一种方式。 (7u95 以上实现了这个 sysprop,但是对于 7u80 以上的 Oracle 7 更新需要付费。如果 OpenJDK 在您的平台上可用,它通常是免费的。)一旦您拥有它,在 SSLSocket
上调用 .setEnabledProtocols
是另一种方式。
编辑 Java 7 或 8 是否支持密码套件:ECDHE-ECDSA-AES256-GCM-SHA384? 我使用的是 Java 1.7_80。
Oracle/Sun 和 OpenJDK 7 不支持 GCM 密码套件。或者确切地说,其中的标准 JSSE 提供程序没有,而且您没有说任何关于更改提供程序的内容。 (IBM Java 使用不同的提供程序,我不知道,但它们大多使用不同的命名格式。)
Oracle 和 OpenJDK 8 确实支持 GCM 套件。但是,较旧的 Oracle 更新不支持 256 位 AES,除非您下载并安装“无限管辖权政策”文件;您可以找到很多其他问题。这是最近修复的; 8u151/152 只需要文本编辑而不是下载文件,8u161/162 及更高版本根本不需要任何更改。 Oracle 9 或任何 OpenJDK 也没有。
【讨论】:
感谢您回答我的问题 JDK 7 从 191 版开始支持 GCM。oracle.com/technetwork/java/javase/2col/…以上是关于带有 TLSv1.2 的 Java 7 连接到 LDAPS 握手失败的主要内容,如果未能解决你的问题,请参考以下文章
已协商获取 `TLSv1。尝试连接到 MS SQL 服务器时,请更新服务器和客户端以至少使用 TLSv1.2
使用 JDBC Thin 和 JKS 的 Oracle 数据库 TLS1.2/SSL 连接
启用TLSv1.2和TLS_RSA_WITH_AES_256_CBC_SHA256密码套件
启用 TLSv1.2 和 TLS_RSA_WITH_AES_256_CBC_SHA256 密码套件