是否有解决方法:java.lang.RuntimeException:无法生成 DH 密钥对

2022-01-19 00:00:00 sockets ssl network-programming java

我正在测试一个 Java 应用程序.我正在尝试使用 DH 密码套件启动 SSL 握手.但我收到以下错误:

I am testing a Java application. I am trying to start an SSL handshake using DH ciphersuite. but I am getting the following error:

java.lang.RuntimeException: Could not generate DH keypair

有人推荐BouncyCastle,但是很多人都报错了,所以如果有其他选择,我不鼓励使用它.

Some people have suggested BouncyCastle, but many people have reported errors with it, so I am not encouraged to use it if there is another alternative.

有人建议从 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files.html" rel="noreferrer">http://www.oracle.com/technetwork/java/javase/downloads/index.html.我确实在 C:Program Files (x86)Javajre7libsecurityjava.securityjava.policy代码>.请注意,我还注意到我已将 Javajre7security 安装在:Program Files (x86)Program Files 中,并且我将两者都替换了.但是,我仍然看到同样的错误.

One have suggested downloading Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files from http://www.oracle.com/technetwork/java/javase/downloads/index.html. I did replaced the following two files java.security and java.policy in C:Program Files (x86)Javajre7libsecurity. Note that I also noticed that I have Javajre7security installed in: Program Files (x86) and Program Files and I replaced both. But, I still see the same error.

这个错误有什么解决方法吗?

Is there any workaround for this error ?

堆栈跟踪:

javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
    at sun.security.ssl.Alerts.getSSLException(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.handleException(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at MyClass.MyClass.myFunction(MyProg.java:78)
    at MyClass.MyClass.main(MyClass.java:233)
Caused by: java.lang.RuntimeException: Could not generate DH keypair
    at sun.security.ssl.DHCrypt.<init>(Unknown Source)
    at sun.security.ssl.ClientHandshaker.serverKeyExchange(Unknown Source)
    at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
    at sun.security.ssl.Handshaker.processLoop(Unknown Source)
    at sun.security.ssl.Handshaker.process_record(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    ... 4 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(DHKeyPairGenerator.java:120)
    at java.security.KeyPairGenerator$Delegate.initialize(Unknown Source)
    ... 11 more

我的代码充当客户端,尝试与远程服务器(网站)启动 SSL 握手.我将客户端的密码套件列表设置为:

My code is acting as a client trying to initiate SSL handshake with a remote server (website). I set the client's cipher suite list to:

{
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_NULL_SHA",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",  
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
"SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
"SSL_DHE_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"
};

Java 支持客户端列表中的所有密码套件.当服务器提供长 DH 密钥时,如何配置 Java 客户端以支持发起 SSL 握手?

All ciphersuites in the client's list are supported by Java. How can configure the Java client to support initiating an SSL handshake when the server offers long DH keys ?

推荐答案

是的,基本上是被#6851461 和#9162249 和#10687200 骗了.无限强度政策不是解决方案.

Yes, basically dupe of #6851461 also #9162249 and #10687200. Unlimited strength policy is NOT the solution.

SSL/TLS 客户端中 DHE(和其他 DH)的素数大小是并且必须根据从服务器接收到的参数设置,客户端不能选择不同的值.(即堆栈跟踪中的 ClientHandshaker.serverKeyExchange.)

The prime size for DHE (and other DH) in SSL/TLS client is and must be set from the parameters received from the server, the client can't choose something different. (That's the ClientHandshaker.serverKeyExchange in the stacktrace.)

您已经拥有优先于 DHE-RSA 的 ECDHE-RSA(在 Java 7 或 6 中运行良好,如果您添加了 ECC 提供程序,例如但不一定是 BouncyCastle),但服务器没有选择它.您不提供纯 RSA;如果您愿意不使用前向保密并且服务器也是,请尝试在 _DHE_RSA 之前(或代替)添加至少一些套件,例如 _RSA_WITH_AES_128_CBC_SHA _RSA_WITH_RC4_128_SHA.

You already have ECDHE-RSA (which works okay in Java 7, or 6 if you add an ECC provider such as but not necessarily BouncyCastle) prioritized over DHE-RSA, and the server didn't choose it. You aren't offering plain-RSA; if you are willing to go without Forward Secrecy and the server is also, try adding at least some suites like _RSA_WITH_AES_128_CBC_SHA _RSA_WITH_RC4_128_SHA before (or instead of) the _DHE_RSA ones.

另一种可能性是要求服务器运营商使用 DH 1024 位,如果他们愿意并允许的话.它实际上还没有被破坏,但它被一些重要的标准所禁止.

Another possibility is to ask the server operator(s) to use DH 1024-bit, if they're willing and permitted. It's not actually broken yet, but it is prohibited by some important standards.

相关文章