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

时间:2018-04-10 07:46:07

标签: java encryption tls1.2 sslhandshakeexception sslcontext

目前我使用的是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警报,长度= 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

之后我尝试运行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
  2. 如何在支持的协议中启用TLSv1.2?
  3. 编辑 Java 7或8是否支持密码套件:ECDHE-ECDSA-AES256-GCM-SHA384
  4. 我正在使用Java 1.7_80。

1 个答案:

答案 0 :(得分:1)

  
      
  1. 什么是RECV TLSv1 ALERT:致命,handshake_failure?
  2.   

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

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

是什么导致handshake_failure?很多事情。实际上不可能从这个警报中判断出问题是什么。

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

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

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

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

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

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

  
      
  1. 编辑Java 7或8是否支持密码套件:ECDHE-ECDSA-AES256-GCM-SHA384?   我使用的是Java 1.7_80。
  2.   

Oracle / Sun和OpenJDK 7不支持GCM密码套件。或者确切地说,它们中的标准JSSE提供程序没有,并且您没有提及有关更改提供程序的任何内容。 (IBM Java使用不同的提供程序,但我不了解它们,但它们大多使用不同的命名格式。)

Oracle和OpenJDK 8确实支持GCM套件。但是,旧的 Oracle 更新不支持256位AES,除非您下载并安装了“无限制管辖权政策”。文件;你可以找到很多其他的Q.这是最近修复的; 8u151 / 152只需要文本编辑而不需要下载文件,8u161 / 162及以上版本根本不需要任何更改。 Oracle 9或任何OpenJDK都不是。