我正在尝试让我的Java客户端使用SSL与C服务器通信。
问题是 - 我没有任何服务器来源,而且我收到握手失败错误:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1657)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:932)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1096)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1123)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1107)
at posslu.Main.main(Main.java:36)
Java Result: 1
经过我现在知道的一些重型线路工作后,工作的C客户端(我无法访问它们的源代码)在客户端 - 服务器hello数据包中都有这些Cipher规范:
Cipher Spec: SSL2_DES_192_EDE3_CBC_WITH_MD5 (0x0700c0)
Cipher Spec: SSL2_IDEA_128_CBC_WITH_MD5 (0x050080)
Cipher Spec: SSL2_RC2_CBC_128_CBC_WITH_MD5 (0x030080)
Cipher Spec: SSL2_RC4_128_WITH_MD5 (0x010080)
Cipher Spec: SSL2_RC4_64_WITH_MD5 (0x080080)
Cipher Spec: SSL2_DES_64_CBC_WITH_MD5 (0x060040)
Cipher Spec: SSL2_RC2_CBC_128_CBC_WITH_MD5 (0x040080)
Cipher Spec: SSL2_RC4_128_EXPORT40_WITH_MD5 (0x020080)
并且所有数据包都以SSLv2协议发送。
这些是来自SSLSocket.getSupportedCipherSuites()方法的规范:
SSL_RSA_WITH_RC4_128_MD5
SSL_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_DSS_WITH_AES_128_CBC_SHA
SSL_RSA_WITH_3DES_EDE_CBC_SHA
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
SSL_RSA_WITH_DES_CBC_SHA
SSL_DHE_RSA_WITH_DES_CBC_SHA
SSL_DHE_DSS_WITH_DES_CBC_SHA
SSL_RSA_EXPORT_WITH_RC4_40_MD5
SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
SSL_RSA_WITH_NULL_MD5
SSL_RSA_WITH_NULL_SHA
SSL_DH_anon_WITH_RC4_128_MD5
TLS_DH_anon_WITH_AES_128_CBC_SHA
SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
SSL_DH_anon_WITH_DES_CBC_SHA
SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
TLS_KRB5_WITH_RC4_128_SHA
TLS_KRB5_WITH_RC4_128_MD5
TLS_KRB5_WITH_3DES_EDE_CBC_SHA
TLS_KRB5_WITH_3DES_EDE_CBC_MD5
TLS_KRB5_WITH_DES_CBC_SHA
TLS_KRB5_WITH_DES_CBC_MD5
TLS_KRB5_EXPORT_WITH_RC4_40_SHA
TLS_KRB5_EXPORT_WITH_RC4_40_MD5
TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA
TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5
现在我想用
Cipher Spec: SSL2_RC4_128_WITH_MD5 (0x010080)
因为C服务器和我的Java客户端似乎都支持它。所以我提出了这个代码:
SSLSocketFactory sslsockfact = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsockfact.createSocket( args[0], args[1] );
sslsocket.setEnabledCipherSuites( new String[] { "SSL_RSA_WITH_RC4_128_MD5" } );
sslsocket.startHandshake();
但由于某些原因,这些密码规范是在客户端hello数据包中发送的:
Cipher Spec: TLS_RSA_WITH_RC4_128_MD5 (0x000004)
Cipher Spec: SSL2_RC4_128_WITH_MD5 (0x010080)
不应该只包含第二个吗? 这会导致服务器以TLSv1协议发送server-hello数据包,并使握手失败。
我继续试图弄清楚发生了什么:
这些是我从getSupportedProtocols()得到的支持协议:
SSLv2Hello
SSLv3
TLSv1
如果我在我的代码中添加这样的内容:
sslsocket.setEnabledProtocols( new String[] { "SSLv2Hello" } );
它说:
Exception in thread "main" java.lang.IllegalArgumentException: SSLv2Hellocannot be enabled unless TLSv1 or SSLv3 is also enabled
如果我切换到:
sslsocket.setEnabledProtocols( new String[] { "SSLv2Hello", "SSLv3" } );
SSLv3中的服务器答案,我得到握手失败......
所以,我不知道如何让这个工作,任何帮助?
是否有可能,不再支持SSLv2,我根本无法在java中使用它?
答案 0 :(得分:1)
JDK JSSE提供程序不支持SSL v2,这是一种固有的不安全协议。 SSLv2Hello支持旨在与某些可能存在协议错误且需要v2 hello的服务器兼容SSLv3。在JDK7中删除了此SSLv2Hello。
对于实际会话,仅支持SSLv3和TLS。因此,如果您的服务器仅支持SSL v2,则需要升级服务器 - v2不安全且不应使用。
SSL_RSA_WITH_RC4_128_MD5
和TLS_RSA_WITH_RC4_128_MD5
是相同的密码套件,但是当通过SSLSocketFactory.getSupportedCipherSuites()
询问支持的套件集时,HotSpot JSSE仅报告前者。当前的Wireshark协议分析器将报告TLS_RSA_WITH_RC4_128_MD5 (0x0004)
,这可能会导致混淆。
另见:
How to initiate ssl connection using SSLv2 http://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html
编辑:因为我上面提到SSLv2非常弃用且不安全,我觉得我现在也应该提到,因为SSLv3 POODLE exploit已经发布,SSLv3也被认为是不安全的并且已被弃用