当我与某些IRC服务器 Build SSL连接(但不是其他服务器 - 可能是由于服务器的首选加密方法),我得到以下异常:
Caused by: java.lang.RuntimeException: Could not generate DH keypair
at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:106)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverKeyExchange(ClientHandshaker.java:556)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:183)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
... 3 more
最终原因:
Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DashoA13*..)
at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:627)
at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:100)
... 10 more
演示此问题的服务器示例是aperture.esper.net:6697(这是一个IRC服务器) . 没有证明问题的服务器示例是kornbluth.freenode.net:6697 . [毫不奇怪,每个网络上的所有服务器共享相同的行为 . ]
我的代码(如上所述在连接到某些SSL服务器时起作用)是:
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new SecureRandom());
s = (SSLSocket)sslContext.getSocketFactory().createSocket();
s.connect(new InetSocketAddress(host, port), timeout);
s.setSoTimeout(0);
((SSLSocket)s).startHandshake();
这是抛出异常的最后一个startHandshake . 是的,'trustAllCerts'还有一些魔力;该代码强制SSL系统不验证证书 . (所以...不是证书问题 . )
显然有一种可能性是esper的服务器配置错误,但我搜索并没有找到任何其他对esper的SSL端口出现问题的人的引用,并且'openssl'连接到它(见下文) . 所以我想知道这是否是Java默认SSL支持的限制,或者其他什么 . 有什么建议?
这是当我使用命令行中的'openssl'连接到aperture.esper.net 6697时发生的情况:
~ $ openssl s_client -connect aperture.esper.net:6697
CONNECTED(00000003)
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
verify return:1
---
Certificate chain
0 s:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
i:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
---
Server certificate
-----BEGIN CERTIFICATE-----
[There was a certificate here, but I deleted it to save space]
-----END CERTIFICATE-----
subject=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
issuer=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
---
No client certificate CA names sent
---
SSL handshake has read 2178 bytes and written 468 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-AES256-SHA
Session-ID: 51F1D40A1B044700365D3BD1C61ABC745FB0C347A334E1410946DCB5EFE37AFD
Session-ID-ctx:
Master-Key: DF8194F6A60B073E049C87284856B5561476315145B55E35811028C4D97F77696F676DB019BB6E271E9965F289A99083
Key-Arg : None
Start Time: 1311801833
Timeout : 300 (sec)
Verify return code: 18 (self signed certificate)
---
如前所述,它确实成功连接,这比我对Java应用程序的说法更多 .
它是否相关,我使用的是OS X 10.6.8,Java版本1.6.0_26 .
21 回答
您可以动态安装提供程序:
1)下载这些 jar :
bcprov-jdk15on-152.jar
bcprov-ext-jdk15on-152.jar
2)将 jar 复制到
WEB-INF/lib
(或你的类路径)3)动态添加提供者:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
...
Security.addProvider(new BouncyCastleProvider());
这是一个相当古老的帖子,但如果您使用Apache HTTPD,则可以限制DH大小 . 见http://httpd.apache.org/docs/current/ssl/ssl_faq.html#javadh
如果您使用的是jdk1.7.0_04,请升级到jdk1.7.0_21 . 该更新已解决该问题 .
问题是素数大小 . Java接受的最大可接受大小是1024位 . 这是一个已知问题(见JDK-6521495) .
我链接的错误报告使用BouncyCastle的JCE实现提到workaround . 希望这应该对你有用 .
UPDATE
这被报告为bug JDK-7044060并且最近修复了 .
但请注意,限制仅提高到2048位 . 对于大小> 2048位,有JDK-8072452 - Remove the maximum prime size of DH Keys;修复似乎是9 .
“Java密码学扩展(JCE)无限强度管辖权政策文件”答案对我不起作用,但BouncyCastle的JCE提供商建议做了 .
以下是我在Mac OSC 10.7.5上使用Java 1.6.0_65-b14-462所采取的步骤
1)下载这些 jar :
bcprov-jdk15on-154.jar
bcprov-ext-jdk15on-154.jar
2)将这些 jar 移到$ JAVA_HOME / lib / ext
3)编辑$ JAVA_HOME / lib / security / java.security,如下所示:security.provider.1 = org.bouncycastle.jce.provider.BouncyCastleProvider
使用JRE重启app并尝试一下
这是我的解决方案(java 1.6),也有兴趣为什么我必须这样做:
我注意到javax.security.debug = ssl,有时使用的密码套件是TLS_DHE _...有时它是TLS_ECDHE ....如果我添加了BouncyCastle,则会发生后者 . 如果选择了TLS_ECDHE,那么大部分工作时间,但不是总是如此,所以添加甚至BouncyCastle提供程序是不可靠的(每隔一次左右都会出现相同的错误) . 我想在Sun SSL实现的某个地方有时会选择DHE,有时它会选择ECDHE .
因此,此处发布的解决方案依赖于完全删除TLS_DHE_密码 . 注意:解决方案不需要BouncyCastle .
因此,创建服务器认证文件:
保存它,因为它将在稍后引用,而不是这里是SSL http get的解决方案,不包括TLS_DHE_密码套件 .
最后是如何使用它(如果从openssl保存证书的路径,则为certFilePath):
上面的答案是正确的,但就解决方法而言,当我将其设置为首选提供程序时,我遇到了BouncyCastle实现的问题:
在我发现的一个论坛帖子中也讨论了这个问题,但没有提到解决方案 . http://www.javakb.com/Uwe/Forum.aspx/java-programmer/47512/TLS-problems
我找到了一个适合我案例的替代解决方案,尽管我对此并不满意 . 解决方案是设置它以使Diffie-Hellman算法根本不可用 . 然后,假设服务器支持替代算法,它将在正常协商期间进行选择 . 显然,这样做的缺点是,如果某人设法找到一个只支持1024位或更少位的Diffie-Hellman的服务器,那么这实际上意味着它将无法在之前工作的地方工作 .
这是给定SSLSocket的代码(在连接之前):
讨厌 .
您可以在jdk中完全禁用DHE,编辑jre / lib / security / java.security并确保禁用DHE,例如 . 喜欢
jdk.tls.disabledAlgorithms=SSLv3, DHE
.如果你仍然被这个问题所困扰 AND 你正在使用Apache httpd v> 2.4.7,试试这个:http://httpd.apache.org/docs/current/ssl/ssl_faq.html#javadh
copied from the url :
以 . . . 开始版本2.4.7,mod_ssl将使用DH参数,其中包括长度超过1024位的素数 . 但是,Java 7及更早版本将它们对DH prime大小的支持限制为最多1024位 .
如果基于Java的客户端因例外java.lang.RuntimeException而中止:无法生成DH密钥对和java.security.InvalidAlgorithmParameterException:Prime大小必须是64的倍数,并且只能在512到1024(包括)范围内,并且httpd logs tlsv1 alert内部错误(SSL警报号80)(在LogLevel信息或更高版本),您可以使用SSLCipherSuite重新排列mod_ssl的密码列表(可能与SSLHonorCipherOrder一起使用),或者您可以使用1024位素数的自定义DH参数,它始终优先于任何内置的DH参数 .
要生成自定义DH参数,请使用
命令 . 或者,您可以使用RFC 2409第6.2节中的以下标准1024位DH参数:
将自定义参数(包括“BEGIN DH PARAMETERS”和“END DH PARAMETERS”行)添加到使用SSLCertificateFile指令配置的第一个证书文件的末尾 .
我在客户端使用java 1.6,它解决了我的问题 . 我没有降低密码套件等,但是在cert文件中添加了自定义生成的DH参数 .
尝试从Java download site下载"Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files"并替换JRE中的文件 .
这对我有用,我甚至不需要使用BouncyCastle - 标准的Sun JCE能够连接到服务器 .
PS . 当我在更改策略文件之前尝试使用BouncyCastle时,我得到了同样的错误(ArrayIndexOutOfBoundsException:64),所以看起来我们的情况非常相似 .
我对Yandex Maps服务器,JDK 1.6和Apache HttpClient 4.2.1也有同样的问题 . 错误是
通过
-Djavax.net.debug=all
启用调试,日志中有一条消息我通过添加BouncyCastle库
bcprov-jdk16-1.46.jar
并在 Map 服务类中注册提供程序来解决此问题提供者在
MapService
的首次使用时注册 .通过升级到JDK 8解决了这个问题 .
我在JDK 1.6.45上使用coldfusion 8并且在给我红色十字架而不是图像时遇到问题,并且cfhttp也无法使用ssl连接到本地网络服务器 .
我的测试脚本用coldfusion 8重现了
这给了我一个非常一般的错误:“I / O异常:对等体未经过身份验证” . 然后我尝试将服务器的证书(包括根证书和中间证书)添加到java密钥库以及coldfusion密钥库,但没有任何帮助 . 然后我调试了问题
得到了
和
然后我认为网络服务器(在我的情况下为apache)具有非常现代的ssl密码并且非常有限(qualys得分)并使用超过1024位的强diffie hellmann密钥 . 显然,coldfusion和java jdk 1.6.45无法管理这个 . odysee的下一步是考虑为java安装替代安全提供程序,我决定使用充气城堡 . 另见http://www.itcsolutions.eu/2011/08/22/how-to-use-bouncy-castle-cryptographic-api-in-netbeans-or-eclipse-for-java-jse-projects/
然后我下载了
从http://www.bouncycastle.org/latest_releases.html并安装在C:\ jdk6_45 \ jre \ lib \ ext下或者你的jdk在哪里,在原始安装的coldfusion 8中它将在C:\ JRun4 \ jre \ lib \ ext下,但我使用的是更新的jdk( 1.6.45)位于coldfusion目录之外 . 将bcprov-ext-jdk15on-156.jar放在\ ext目录中非常重要(这花了我两个小时左右的时间和一些头发;-)然后我编辑了文件C:\ jdk6_45 \ jre \ lib \ security \ java.security(使用wordpad而不是editor.exe!)并为新提供程序添加一行 . 之后列表看起来像
(见第1位新的)
然后完全重启coldfusion服务 . 你可以
并享受这种感觉......当然
多么美好的一夜,多么美好的一天 . 希望这将有助于(部分或全部)到那里的人 . 如果您有任何疑问,请发邮件至info ...(上面的域名) .
您可能有不正确的Maven依赖项 . 您必须在Maven依赖关系层次结构中找到这些库:
如果您有这些依赖项是错误,那么您应该这样做:
添加依赖项:
从包含错误依赖项的工件中排除这些依赖项,在我的例子中它是:
如果服务器支持不包含DH的密码,则可以强制客户端选择该密码并避免DH错误 . 如:
请记住,从长远来看,指定精确的密码很容易破损 .
我们得到了同样的确切异常错误返回,修复它很容易在网上冲浪后 .
我们下载了oracle.com上可以找到的最高版本的jdk,安装它并将Jboss应用程序服务器指向已安装的新jdk的目录 .
重新启动Jboss,重新处理,问题解决!!!
我有Bamboo 5.7 Gradle项目Apache出现此错误 . Gradle尝试通过SSL从我们的一台服务器获取一些依赖项 .
Solution:
使用OpenSSL:
示例输出:
将输出附加到证书文件(对于Apache -
SSLCertificateFile
param)重启apache
重启Bamboo
尝试再次构建项目
我曾经使用IBM JDK在java SVN客户端访问svn.apache.org时遇到类似的错误 . 目前,svn.apache.org用户使用密码首选项 .
在使用数据包捕获/ javax.net.debug = ALL运行一次之后,我只能将一个DHE密码列入黑名单并且事情对我有用(而ECDHE则是协商的) .
如果不容易更改客户端,这是一个很好的快速解决方案 .
我在运行JDK 6的CentOS服务器上遇到SSL错误 .
我的计划是安装一个更高的JDK版本(JDK 7)与JDK 6共存但事实证明仅仅安装带有
rpm -i
的新JDK是不够的 .JDK 7安装只能通过
rpm -U
升级选项成功,如下图所示 .1.下载JDK 7
2. RPM安装失败
3. RPM升级成功
4.确认新版本
最近我有同样的问题,并将jdk版本从 1.6.0_45 升级到 jdk1.7.0_191 后解决了这个问题 .
对我来说,以下命令行修复了这个问题:
java -jar -Dhttps.protocols=TLSv1.2 -Ddeployment.security.TLSv1.2=true -Djavax.net.debug=ssl:handshake XXXXX.jar
我使用的是JDK 1.7.0_79