When I make an SSL connection with some IRC servers (but not others - presumably due to the server's preferred encryption method) I get the following exception:
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
Final cause:
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
An example of a server that demonstrates this problem is aperture.esper.net:6697 (this is an IRC server). An example of a server that does not demonstrate the problem is kornbluth.freenode.net:6697. [Not surprisingly, all servers on each network share the same respective behaviour.]
My code (which as noted does work when connecting to some SSL servers) is:
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();
It's that last startHandshake that throws the exception. And yes there is some magic going on with the 'trustAllCerts'; that code forces the SSL system not to validate certs. (So... not a cert problem.)
Obviously one possibility is that esper's server is misconfigured, but I searched and didn't find any other references to people having problems with esper's SSL ports, and 'openssl' connects to it (see below). So I'm wondering if this is a limitation of Java default SSL support, or something. Any suggestions?
Here's what happens when I connect to aperture.esper.net 6697 using 'openssl' from commandline:
~ $ 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)
---
As noted, after all that, it does connect successfully which is more than you can say for my Java app.
Should it be relevant, I'm using OS X 10.6.8, Java version 1.6.0_26.
I have the same problem with Yandex Maps server, JDK 1.6 and Apache HttpClient 4.2.1. The error was
with enabled debug by
-Djavax.net.debug=all
there was a message in a logI have fixed this problem by adding BouncyCastle library
bcprov-jdk16-1.46.jar
and registering a provider in a map service classA provider is registered at the first usage of
MapService
.Try downloading "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files" from the Java download site and replacing the files in your JRE.
This worked for me and I didn't even need to use BouncyCastle - the standard Sun JCE was able to connect to the server.
PS. I got the same error (ArrayIndexOutOfBoundsException: 64) when I tried using BouncyCastle before changing the policy files, so it seems our situation is very similar.
You can installing the provider dynamically:
1) Download these jars:
bcprov-jdk15on-152.jar
bcprov-ext-jdk15on-152.jar
2) Copy jars to
WEB-INF/lib
(or your classpath)3) Add provider dynamically:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
...
Security.addProvider(new BouncyCastleProvider());
Solved the problem by upgrading to JDK 8.
If the server supports a cipher that does not include DH, you can force the client to select that cipher and avoid the DH error. Such as:
Keep in mind that specifying an exact cipher is prone to breakage in the long run.
I encountered the SSL error on a CentOS server running JDK 6.
My plan was to install a higher JDK version (JDK 7) to co-exist with JDK 6 but it turns out that merely installing the newer JDK with
rpm -i
was not enough.The JDK 7 installation would only succeed with the
rpm -U
upgrade option as illustrated below.1. Download JDK 7
2. RPM installation fails
3. RPM upgrade succeeds
4. Confirm the new version