我读了一篇关于当服务器发出长度超过1024位的密钥时出现错误'无法生成DH密钥对'的帖子.下载JCE无限量罐子应该可以解决这个问题.在测试环境中,我遇到了以下内容,对于同一个Web服务器,如果我使用Java 6,在执行https查询时没有出现任何错误,但是如果我使用Java 7则会得到"无法生成DH密钥对".
我尝试更换JCE无效的jar文件,但仍然得到相同的错误.自2007年以来报告了该错误,但为什么它运行Java 6而不是Java 7?要下载的文件不是正确的吗?我从以前的帖子Java获得了链接:为什么SSL握手会给出"无法生成DH密钥对"的异常?.
此时我不知道该怎么办.如果我尝试加载BouncyCastle提供程序,我会得到一个ArrayOutOfIndex异常.我的服务器只允许DH算法,所以我不能使用上面帖子中建议的其他算法.
dav*_*085 11
一些补充或澄清:
(Suncle)Java 7自7u09以来默认情况下使用更合理的密码组顺序,与7u04中看似随机的顺序不同.(我在04和09之间没有测试.)此命令在DHE之前放置ECDHE和普通RSA(也称为akRSA),因此如果服务器支持ECDHE或RSA并且同意客户端偏好,则可以避免此问题.(或ECDH固定,但实际上没有人使用它.)如果服务器坚持DHE(无论出于何种原因)并使用DH> 1024位,你仍然有问题.
如果提问者(或其他任何人)连接到真正需要整数DH(而不是ECDH或RSA)的服务器,那么在8之前使用Java的唯一方法是让服务器使用DH 1024位.哪种AFAWK在技术上可以安全使用几年,但由于NIST等重要机构禁止使用AFAWK(请参阅csrc.nist.gov上的Special Pub 800-57).(即使RSA 1024实际上还没有被破坏,但它很快就会被破坏,所以是禁止的.)
"无限强度政策"与这个问题无关,或者至少不是直接相关的,#6851461的好答案并没有说明.它不会改变SunJCE中对DH参数的限制,这被(错误地)视为标准问题而非强度问题.(具体来说,它采用了以前对DSA正确的限制,并将它们应用于DH.)它确实启用了AES-256和SHA-2(仅适用于TLSv1.2)套件,并且给出了一个足够奇怪的首选项列表,将选择结果从DHE(失败)更改为非DHE(工作).
您不需要完全返回到Java 6列表,只需要通过DHE优先处理其他密钥交换,或者对于一个顽固的服务器完全删除DHE.除非传统服务器绝对需要,否则你绝对不应该回到启用任何EXPORT或单DES套件; 他们几年来一直没有安全,并且在默认情况下仍然保持启用的时间远远超过应有的时间.
我偶然发现了与SSLScokets相同的问题,我想我已经确定了使用Java 7进行回归的原因.原因是客户端和服务器之间协商的密码.
默认情况下,Java 6为TLS连接启用这些密码(按优先级顺序):
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
TLS_EMPTY_RENEGOTIATION_INFO_SCSV
Run Code Online (Sandbox Code Playgroud)
Java 7支持以下密码:
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
SSL_RSA_WITH_RC4_128_SHA
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDHE_RSA_WITH_RC4_128_SHA
TLS_ECDH_ECDSA_WITH_RC4_128_SHA
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDH_RSA_WITH_RC4_128_SHA
TLS_EMPTY_RENEGOTIATION_INFO_SCSV
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
SSL_RSA_WITH_RC4_128_MD5
TLS_DHE_DSS_WITH_AES_128_CBC_SHA
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
SSL_RSA_WITH_3DES_EDE_CBC_SHA
Run Code Online (Sandbox Code Playgroud)
使用Diffie-Hellman的密码在Java 7上具有更高的优先级,但它们似乎不支持长度超过1024位的密钥,除非安装了强加密包.
我使用的解决方法是在以下位置指定Java 6启用的密码SSLSocket:
SSLSocketFactory socketFactory = SSLContext.getInstance("TLS").getSocketFactory();
SSLSocket socket = (SSLSocket) socketFactory.createSocket(InetAddress.getByName(hostname), port);
socket.setEnabledCipherSuites(new String[] {
"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",
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV"});
socket.startHandshake();
Run Code Online (Sandbox Code Playgroud)
小智 6
鉴于您使用的是最新的java版本并仍然出现错误,您可以更改java.security中的设置(例如,在文件夹C:\ Program Files\Java\jre1.8.0_xx\lib\security中)
# Example:
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
jdk.tls.disabledAlgorithms=SSLv3, RC4
Run Code Online (Sandbox Code Playgroud)
在jdk.tls.disabledAlgorithms中将DH添加为禁用算法
jdk.tls.disabledAlgorithms=SSLv3, RC4, DH
Run Code Online (Sandbox Code Playgroud)
重启tomcat或重新运行程序.