SSLSocket.getEnabledProtocols()
方法返回以下内容:[SSLv2Hello, SSLv3, TLSv1]
。事实上,当我调用connect()
并打开SSL调试时,我看到使用了v2客户端问候语:
main, WRITE: TLSv1 Handshake, length = 81
main, WRITE: SSLv2 client hello message, length = 110
但我发现有两个(不可否认的旧)参考文献说JSSE 不支持SSL版本2:
来自Fundamental Networking in Java:
'SSLv2Hello'是一种伪协议,它允许Java使用SSLv2'hello消息'发起握手。这 not 导致使用SSLv2协议,而Java根本不支持该协议。
J2SDK 1.4及更高版本中的JSSE实现实现了SSL 3.0和TLS 1.0。它没有实现SSL 2.0。
现在,我的理解是只有在客户端 支持SSL版本2.0时才会发送版本2.0客户端问候。来自RFC 2246:
支持SSL 2.0版服务器的TLS 1.0客户端必须发送SSL 版本2.0客户端问候消息[SSL2] ... 警告:发送版本2.0客户端问候消息的能力将逐步淘汰。
那么为什么Java会使用它?
答案 0 :(得分:18)
Sun的JSSE不支持SSLv2,但它支持SSlv2ClientHello
,以支持一些需要它的SSL服务器。您可以通过从启用的协议中删除它来关闭它。
IBM的JSSE完全支持SSLv2。
例如,一些较旧的服务器 实现只说SSLv3和 不懂TLS。理想情况下,这些 实现应该协商 SSLv3,但有些只是挂断。对于 向后兼容,一些服务器 实现(如SunJSSE)发送 SSLv3 / TLS ClientHellos封装在 SSLv2 ClientHello数据包。一些 服务器不接受这种格式 这些情况使用setEnabledProtocols 禁用封装的发送 SSLv2 ClientHellos。
我认为'服务器实现'应该是上面的“SSL实现”。
编辑:谢谢你引用我的书!答案 1 :(得分:0)
我遇到了同样的问题,我们的 RCP 应用程序出现了这个错误,它试图访问我们只处理 TLS 协议的 nginx。但是我们使用的 openjdk 有一个带有 TLS 的错误,在某些情况下会以:javax.net.ssl.SSLException: Received fatal alert: bad_record_mac
结尾。所以我试图找到一种方法来使用不同的协议来进行像 SSLv3 这样的握手。起初我认为 SSLv2Hello
是握手协议!但事实并非如此!
SSLv2 从未在 sun jdk 或 openjdk 中实现,这个 SSLv2Hello
不是握手的实际协议,它是为了向后兼容(我的猜测是因为某些服务器存在的可能性)并且它会用于协商将用于实际握手的可用协议!
在此 link 搜索来自 Stoinov
的答案时,他很好地包装了答案。