目前我使用的是Java 7,无法连接到LDAPS。我尝试使用以下代码,但仍然无法连接:
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
ctx.init(null, null, null);
SSLContext.setDefault(ctx);
以下是我从程序中得到的错误:
2018-04-10 15:21:23,446 信息 [标准输出] (EJB 默认值 - 1) EJB 默认值 - 1,写入:TLSv1.2 握手,长度 = 221
2018-04-10 15:21:23,446 信息 [标准输出] (EJB 缺省值 - 1) EJB 缺省值 - 1,读取:TLSv1.2 警报,长度 = 2
2018-04-10 15:21:23,446 信息 [标准输出] (EJB 缺省值 - 1) EJB 缺省值 - 1, RECV TLSv1 警报: 致命, handshake_failure
2018-04-10 15:21:23,446 信息 [stdout] (EJB 缺省值 - 1) EJB 缺省值 - 1,称为 closeSocket()
2018-04-10 15:21:23,446 信息 [stdout] (EJB 缺省值 - 1) EJB 缺省值 - 1,处理异常:javax.net.ssl.SSLHandshake异常:收到致命警报:handshake_failure
之后,我尝试运行协议测试来检查支持的协议:
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
它都会导致错误
我的问题是:
- 什么是
RECV TLSv1 ALERT: fatal, handshake_failure
? - 如何在支持的协议中启用TLSv1.2?
- 编辑Java 7 或 8 是否支持密码套件:
ECDHE-ECDSA-AES256-GCM-SHA384
?
我使用的是Java 1.7_80。
- 什么是 RECV TLSv1 警报:致命,handshake_failure?
这意味着我们收到了来自服务器的警报(在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握手的一些(但不是全部)变体。
你可能猜到我推荐第一个。
- 如何在支持的协议中启用TLSv1.2?
您不需要在受支持的协议中启用它;您需要在启用的协议中启用它,并且您已经这样做了。使用SSLContext.getInstance("TLSv1.2")
是一种方式。在Java 8中,但不是(编辑)7的免费Oracle更新,使用syspropjdk.tls.client.protocols
是另一种方式。(7u95 更高版本实现此系统,但对于 Oracle 7 以上的更新,7u80 以上需要付费。如果OpenJDK在你的平台上可用,它通常是免费的。在SSLSocket
上打电话给.setEnabledProtocols
,一旦你拥有它,是另一种方式。
- Edit 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也没有。