带有 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 密码套件

带有 SVN 1.7.20 的 Mac 10.11:无法连接到 URL 上的存储库

如何在本地使用 java 连接到带有 spark 的 Google 大查询?