当我与某些IRC服务器建立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
Run Code Online (Sandbox Code Playgroud)
最终原因:
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
Run Code Online (Sandbox Code Playgroud)
演示此问题的服务器示例是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();
Run Code Online (Sandbox Code Playgroud)
这是抛出异常的最后一个startHandshake.是的,'trustAllCerts'有一些魔力; 该代码强制SSL系统不验证证书.(所以...不是证书问题.) …
当你谷歌这个例外:java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty,会出现多个结果.然而,没有确定的解决方案,只有猜测.
当我尝试使用SSL打开连接时,问题出现了(至少在我的情况下).它在我的Windows机器上工作正常,但是当我将它部署到linux机器(安装了sun的jre)时,它会因上述异常而失败.
问题是JRE的默认信任库由于某种原因是空的(大小只有32字节,而在Windows上是80kb).
当我将我的jre/lib/security/cacerts文件从Windows 复制到linux时,它运行正常.
问题是 - 为什么linux jre有一个空的信任存储?
请注意,这种情况发生在使用AMI linux的Amazon EC2实例上,因此可能是由于一些亚马逊政策(我认为java已预先安装,但我不确定)