0

目前我正在使用 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

我添加了以下行以禁用 TLSv1 并在以下位置启用 TLSv1.2 java.security

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错误


我的问题是:

  1. 是什么RECV TLSv1 ALERT: fatal, handshake_failure
  2. 如何在支持的协议中启用 TLSv1.2?
  3. 编辑Java 7 或 8 是否支持密码套件:ECDHE-ECDSA-AES256-GCM-SHA384

我正在使用 Java 1.7_80。

4

1 回答 1

4
  1. 什么是 RECV TLSv1 ALERT: fatal, handshake_failure ?

这意味着我们(在 Java SSL/TLS 代码中,JSSE 中)收到了来自服务器的警报,其严重性为致命并键入 handshake_failure。由于它在发送一个握手消息后立即发生,如果您没有从您发布的日志提取中省略其他相关信息,我们可能会收到此警报以响应 ClientHello 消息,这是发送的第一个握手消息。

此处的“TLSv1”可能具有误导性。它是SSLSocketImpl对象中的一个变量,初始化为 TLSv1 并且在握手完成之前不会更新,因此此时它不能准确地指示正在使用的协议版本。前面的日志条目“READ: TLSv1.2 Alert, length = 2”确实显示了接收到的实际版本,并确认服务器至少正在尝试执行 TLS1.2。

是什么导致握手失败?很多很多的东西。从这个警报中几乎不可能判断出问题所在。

  • 您最好的选择是查看服务器日志并找出它为什么说它发送了警报。

  • 你最糟糕的选择是查看我们发送的 ClientHello——其中大部分应该在你发布的行之前由 JSSE 记录——并考虑那里的所有内容,或者不在那里,服务器可能不喜欢哪些值或缺席,并尝试更改它们中的每一个。有些比较容易更改,有些则非常困难,因此这可能需要数小时到数周的时间。

  • 如果您有任何其他客户端成功连接到同一服务器,则中间选项是查看 ClientHello 中有效的和无效的之间的差异,并考虑这些差异。作为这种情况的一种情况,如果您拥有或获得 OpenSSL,则命令行openssl s_client可以快速且相当简单地用于测试 SSL/TLS 握手的一些(但不是全部)变体。

你可能会猜到我推荐第一个。

  1. 如何在支持的协议中启用 TLSv1.2?

您无需在受支持的情况下启用它;您需要在启用的协议中启用它,并且您已经这样做了。使用 SSLContext.getInstance("TLSv1.2")是一种方式。在 Java 8 但不是(编辑)7 的免费 Oracle 更新中,使用 syspropjdk.tls.client.protocols是另一种方式。(7u95 以上实现了这个 sysprop,但是对于 7u80 以上的 Oracle 7 更新需要付费。如果 OpenJDK 在您的平台上可用,它通常是免费的。)调用.setEnabledProtocolsSSLSocket一旦你拥有它,是另一种方式。

  1. 编辑 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 也没有。

于 2018-04-11T10:28:42.017 回答