带有TLSv1.2的Java 7连接到LDAPS握手失败

目前我使用的是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,WRITE:TLSv1.2握手,长度= 221

2018-04-10 15:21:23,446 INFO [stdout](EJB默认值 – 1)EJB默认值 – 1,READ:TLSv1.2 Alert,length = 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,处理exception:javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure


之后我尝试运行Protocol Test来检查支持的协议:

 Supported Protocols: 5 SSLv2Hello SSLv3 TLSv1 TLSv1.1 TLSv1.2 Enabled Protocols: 1 TLSv1 

我在下面添加了以下行来禁用TLSv1并在java.security启用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错误


我的问题是:

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

我正在使用Java 1.7_80。

  1. 什么是RECV TLSv1警告:致命,握手_失败?

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

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

是什么导致handshake_failure? 很多东西。 实际上不可能从这个警报中分辨出问题是什么。

  • 您最好的选择是查看服务器日志并找出它发送警报的原因。

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

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

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

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

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

  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,除非您下载并安装“无限制管辖权政策”文件; 你可以找到很多其他的Q. 这是最近修复的; 8u151 / 152只需要文本编辑而不需要下载文件,8u161 / 162及以上版本根本不需要任何更改。 Oracle 9或任何OpenJDK都不是。