By sam


2011-07-27 21:29:08 8 Comments

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/[email protected]
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/[email protected]
verify return:1
---
Certificate chain
 0 s:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
   i:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
---
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/[email protected]
issuer=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
---
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.

21 comments

@Sam 2018-08-08 19:33:51

Recently I have the same issue and after upgrading jdk version from 1.6.0_45 to jdk1.7.0_191 which resolved the issue.

@Jose Antonio Sánchez Pujante 2018-03-22 09:03:54

It is possible that you have incorrect Maven dependencies. You must find these libraries in Maven dependency hierarchy:

bcprov-jdk14, bcpkix-jdk14, bcmail-jdk14

If you have these dependencies that is the error, and you should do this:

Add the dependency:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcmail-jdk15on</artifactId>
    <version>1.59</version>
</dependency>

Exclude these dependencies from the artifact that included the wrong dependencies, in my case it is:

<dependency>
    <groupId>com.lowagie</groupId>
    <artifactId>itext</artifactId>
    <version>2.1.7</version>
    <exclusions>
        <exclusion>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bctsp-jdk14</artifactId>                
        </exclusion>
        <exclusion>
            <groupId>bouncycastle</groupId>
            <artifactId>bcprov-jdk14</artifactId>               
        </exclusion>
        <exclusion>
            <groupId>bouncycastle</groupId>
            <artifactId>bcmail-jdk14</artifactId>               
        </exclusion>
    </exclusions>       
</dependency>

@David Guyon 2018-03-22 09:20:47

The question already received many answers and has one validated answer. Moreover the question has been asked more than 6 years ago. I'm not sure if it's still relevant.

@Vivin Paliath 2011-07-27 22:39:41

The problem is the prime size. The maximum-acceptable size that Java accepts is 1024 bits. This is a known issue (see JDK-6521495).

The bug report that I linked to mentions a workaround using BouncyCastle's JCE implementation. Hopefully that should work for you.

UPDATE

This was reported as bug JDK-7044060 and fixed recently.

Note, however, that the limit was only raised to 2048 bit. For sizes > 2048 bit, there is JDK-8072452 - Remove the maximum prime size of DH Keys; the fix appears to be for 9.

@Paŭlo Ebermann 2011-07-27 22:56:05

+1. Everyone who has a Sun Developer Network Account, please vote for this bug.

@sam 2011-07-28 16:23:53

Thanks. Seems a pretty serious problem given the existence of servers which request a larger size! :( I tried BouncyCastle; if you set it up as preferred provider it crashes with a different exception (sigh), and I can't see an obvious way to use that just for DH. However, I found an alternative solution, which I'll add as a new answer. (It's not pretty.)

@N.. 2013-08-26 05:20:56

Cool. This has been fixed in newer versions of Java. But my question is about using older version.. When I use older version, sometimes it works and sometimes it gives above exception..Why so random behaviour? If its a bug in java, then I guess it should never work?

@mjj1409 2015-03-20 21:52:35

The BouncyCastle's JCE provider implementation worked for me

@bebbo 2015-05-16 20:06:38

This has not been fixed. The limit was changed from 1024 to 2048. Thus a prime size > 2048 yields the same error

@fuzzyTew 2015-06-30 22:19:10

The 2048 fix was backported to IcedTea 2.5.3 . Newer versions of IcedTea increased it to 4096.

@ajon 2015-07-03 17:31:37

When I updated Java on the machine, this issue went away.

@samy 2015-08-17 10:40:47

Is it also fixed for 4096bit keys with java 1.8.0_51 on Ubuntu 14.04? Because I'm getting the same error while trying to connect to a server.

@sleske 2016-02-09 16:05:10

@bebbo: Correct. Support for primes > 2048 bit was requested in JDK-8072452 - Remove the maximum prime size of DH Keys.

@bebbo 2016-02-09 17:19:10

@sleske: A request does not mean it has already been changed. Such a limitation is simply superfluous. Right now it's not available.

@user1332994 2016-05-15 04:36:46

The problem is the DH prime size. The maximum-acceptable size that Java accepts is 2048 bits. While we wait for Oracle to expand the limit, you can compile with Excelsior Jet which has an expanded limit.

@plugwash 2017-06-02 15:21:53

@N it depends on the server configuration. The bug only manifests if the server chooses a DHE ciphersuite and then sends a prime that the client considers too large. It is seen less often with Java 7 than Java 6 because Java 7 supports ECDHE and most server's preffer ECDHE over DHE.

@Saheed 2017-03-16 16:25:46

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

wget -O /root/jdk-7u79-linux-x64.rpm --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; o raclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.rpm"

2. RPM installation fails

rpm -ivh jdk-7u79-linux-x64.rpm
Preparing...                ########################################### [100%]
        file /etc/init.d/jexec from install of jdk-2000:1.7.0_79-fcs.x86_64 conflicts with file from package jdk-2000:1.6.0_43-fcs.x86_64

3. RPM upgrade succeeds

rpm -Uvh jdk-7u79-linux-x64.rpm
Preparing...                ########################################### [100%]
   1:jdk                    ########################################### [100%]
Unpacking JAR files...
        rt.jar...
        jsse.jar...
        charsets.jar...
        tools.jar...
        localedata.jar...
        jfxrt.jar...

4. Confirm the new version

java -version
java version "1.7.0_79"
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)

@covener 2017-01-07 17:00:45

I used to get a similar error accessing svn.apache.org with java SVN clients using an IBM JDK. Currently, svn.apache.org users the clients cipher preferences.

After running just once with a packet capture / javax.net.debug=ALL I was able to blacklist just a single DHE cipher and things work for me (ECDHE is negotiated instead).

.../java/jre/lib/security/java.security:
    jdk.tls.disabledAlgorithms=SSL_DHE_RSA_WITH_AES_256_CBC_SHA

A nice quick fix when it is not easy to change the client.

@Raffael Meier 2017-01-05 16:28:13

I use coldfusion 8 on JDK 1.6.45 and had problems with giving me just red crosses instead of images, and also with cfhttp not able to connect to the local webserver with ssl.

my test script to reproduce with coldfusion 8 was

<CFHTTP URL="https://www.onlineumfragen.com" METHOD="get" ></CFHTTP>
<CFDUMP VAR="#CFHTTP#">

this gave me the quite generic error of " I/O Exception: peer not authenticated." I then tried to add certificates of the server including root and intermediate certificates to the java keystore and also the coldfusion keystore, but nothing helped. then I debugged the problem with

java SSLPoke www.onlineumfragen.com 443

and got

javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair

and

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:107)
    ... 10 more

I then had the idea that the webserver (apache in my case) had very modern ciphers for ssl and is quite restrictive (qualys score a+) and uses strong diffie hellmann keys with more than 1024 bits. obviously, coldfusion and java jdk 1.6.45 can not manage this. Next step in the odysee was to think of installing an alternative security provider for java, and I decided for bouncy castle. see also http://www.itcsolutions.eu/2011/08/22/how-to-use-bouncy-castle-cryptographic-api-in-netbeans-or-eclipse-for-java-jse-projects/

I then downloaded the

bcprov-ext-jdk15on-156.jar

from http://www.bouncycastle.org/latest_releases.html and installed it under C:\jdk6_45\jre\lib\ext or where ever your jdk is, in original install of coldfusion 8 it would be under C:\JRun4\jre\lib\ext but I use a newer jdk (1.6.45) located outside the coldfusion directory. it is very important to put the bcprov-ext-jdk15on-156.jar in the \ext directory (this cost me about two hours and some hair ;-) then I edited the file C:\jdk6_45\jre\lib\security\java.security (with wordpad not with editor.exe!) and put in one line for the new provider. afterwards the list looked like

#
# List of providers and their preference orders (see above):
#
security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=sun.security.mscapi.SunMSCAPI

(see the new one in position 1)

then restart coldfusion service completely. you can then

java SSLPoke www.onlineumfragen.com 443 (or of course your url!)

and enjoy the feeling... and of course

what a night and what a day. Hopefully this will help (partially or fully) to someone out there. if you have questions, just mail me at info ... (domain above).

@Evgeny Lebedev 2016-12-05 07:59:02

I've got this error with Bamboo 5.7 + Gradle project + Apache. Gradle tried to get some dependencies from one of our servers via SSL.

Solution:

  1. Generate DH Param:

with OpenSSL:

openssl dhparam 1024

example output:

-----BEGIN DH PARAMETERS-----
MIGHfoGBALxpfMrDpImEuPlhopxYX4L2CFqQov+FomjKyHJrzj/EkTP0T3oAkjnS
oCGh6p07kwSLS8WCtYJn1GzItiZ05LoAzPs7T3ST2dWrEYFg/dldt+arifj6oWo+
vctDyDqIjlevUE+vyR9MF6B+Rfm4Zs8VGkxmsgXuz0gp/9lmftY7AgEC
-----END DH PARAMETERS-----
  1. Append output to certificate file (for Apache - SSLCertificateFile param)

  2. Restart apache

  3. Restart Bamboo

  4. Try to build project again

@rico-chango 2016-10-18 20:17:07

For me, the following command line fixed the issue:

java -jar -Dhttps.protocols=TLSv1.2 -Ddeployment.security.TLSv1.2=true -Djavax.net.debug=ssl:handshake XXXXX.jar

I am using JDK 1.7.0_79

@Ramgau 2017-03-02 03:16:10

I faced same situation using JDK 1.7.0_xx. BY default issue will be solved after using jdk 1.8. But sometime we can not upgrade jdk quickly. So my issue solved after adding system configuration: System.setProperty("https.protocols", "TLSv1.2"); System.setProperty("deployment.security.TLSv1.2", "true");

@v.ladynev 2015-11-21 17:11:15

I have the same problem with Yandex Maps server, JDK 1.6 and Apache HttpClient 4.2.1. The error was

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

with enabled debug by -Djavax.net.debug=all there was a message in a log

Could not generate DH keypair

I have fixed this problem by adding BouncyCastle library bcprov-jdk16-1.46.jar and registering a provider in a map service class

public class MapService {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public GeocodeResult geocode() {

    }

}

A provider is registered at the first usage of MapService.

@comeOnGetIt 2016-04-28 20:05:05

Where did you write this static block of code ?

@v.ladynev 2016-04-29 06:07:58

@comeOnGetIt I update my answer.

@anre 2016-06-01 15:08:47

Solved the problem by upgrading to JDK 8.

@mjj1409 2015-03-20 22:12:34

The "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files" answer did not work for me but The BouncyCastle's JCE provider suggestion did.

Here are the steps I took using Java 1.6.0_65-b14-462 on Mac OSC 10.7.5

1) Download these jars:

2) move these jars to $JAVA_HOME/lib/ext

3) edit $JAVA_HOME/lib/security/java.security as follows: security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider

restart app using JRE and give it a try

@DiveInto 2015-04-27 01:37:40

works for me! though not quite sure what I am doing.

@TinusSky 2015-07-07 13:42:31

security.provider.2=org.bouncycastle.jce.provider.BouncyCast‌​leProvider did work better, putting it on 1. resulted in errors in default software.

@v.ladynev 2015-11-22 09:19:56

This works for me too, but I have added a provider dynamically. Reffer my answer here for details.

@Majid 2017-04-27 10:21:31

Thanks it works on java 1.6

@phillipuniverse 2017-05-26 20:43:05

Thanks a ton, this worked for me and was required in order to successfully build the Tomcat 7.0.78 source.

@Peter Azuka Molokwu 2016-04-05 16:20:42

We got the same exact exception error returned, to fix it was easy after hours surfing the internet.

We downloaded the highest version of jdk we could find on oracle.com, installed it and pointed Jboss application server to the directory of the installed new jdk.

Restarted Jboss, reprocessed, problemo fixed!!!

@pka 2015-11-14 18:57:58

If you are still bitten by this issue AND you are using Apache httpd v> 2.4.7, try this: http://httpd.apache.org/docs/current/ssl/ssl_faq.html#javadh

copied from the url:

Beginning with version 2.4.7, mod_ssl will use DH parameters which include primes with lengths of more than 1024 bits. Java 7 and earlier limit their support for DH prime sizes to a maximum of 1024 bits, however.

If your Java-based client aborts with exceptions such as java.lang.RuntimeException: Could not generate DH keypair and java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive), and httpd logs tlsv1 alert internal error (SSL alert number 80) (at LogLevel info or higher), you can either rearrange mod_ssl's cipher list with SSLCipherSuite (possibly in conjunction with SSLHonorCipherOrder), or you can use custom DH parameters with a 1024-bit prime, which will always have precedence over any of the built-in DH parameters.

To generate custom DH parameters, use the

openssl dhparam 1024

command. Alternatively, you can use the following standard 1024-bit DH parameters from RFC 2409, section 6.2:

-----BEGIN DH PARAMETERS-----
MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR
Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL
/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC
-----END DH PARAMETERS-----

Add the custom parameters including the "BEGIN DH PARAMETERS" and "END DH PARAMETERS" lines to the end of the first certificate file you have configured using the SSLCertificateFile directive.


I am using java 1.6 on client side, and it solved my issue. I didn't lowered the cipher suites or like, but added a custom generated DH param to the cert file..

@plugwash 2017-06-02 15:39:40

Be aware that it is now believed that 1024 bit DH is computationally feasible (though hellishly expensive) to break.

@Tor 2015-07-10 07:44:48

You can disable DHE completely in your jdk, edit jre/lib/security/java.security and make sure DHE is disabled, eg. like

jdk.tls.disabledAlgorithms=SSLv3, DHE.

@Abhiram mishra 2016-04-19 07:09:49

It did not work for me. I am using java 1.6.0_33

@hoangthienan 2016-06-27 01:19:33

that is only available in JDK 1.7 and later. link

@MrSmith42 2018-02-12 15:52:04

Solved the problem for me JDK 1.8.0_144-b01

@Jason Martin 2015-07-01 23:33:36

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:

String pickedCipher[] ={"TLS_RSA_WITH_AES_256_CBC_SHA"};
sslsocket.setEnabledCipherSuites(pickedCipher);

Keep in mind that specifying an exact cipher is prone to breakage in the long run.

@angelcorral 2015-05-07 12:44:48

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());

@ishanbakshi 2016-01-04 03:33:34

This solution works well, and was a good fit for my case since I wanted to make the changes only at the project level and not at the server/environment level. Thanks

@Raphael Roth 2016-03-23 07:41:24

does not work for me

@Japheth Ongeri - inkalimeva 2016-11-11 12:19:14

Thanks! this worked for me. In my case it was itext importing bcp 1.4 causing emails to google to fail.

@Hadi Momenzadeh 2017-05-23 07:29:00

Tnx, it worked for mee too. :)

@Bertl 2014-11-19 17:08:12

This is a quite old post, but if you use Apache HTTPD, you can limit the DH size. See http://httpd.apache.org/docs/current/ssl/ssl_faq.html#javadh

@Zsozso 2013-08-15 13:47:50

Here is my solution (java 1.6), also would be interested why I had to do this:

I noticed from the javax.security.debug=ssl, that sometimes the used cipher suite is TLS_DHE_... and sometime it is TLS_ECDHE_.... The later would happen if I added BouncyCastle. If TLS_ECDHE_ was selected, MOST OF the time it worked, but not ALWAYS, so adding even BouncyCastle provider was unreliable (failed with same error, every other time or so). I guess somewhere in the Sun SSL implementation sometimes it choose DHE, sometimes it choose ECDHE.

So the solution posted here relies on removing TLS_DHE_ ciphers completely. NOTE: BouncyCastle is NOT required for the solution.

So create the server certification file by:

echo |openssl s_client -connect example.org:443 2>&1 |sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'

Save this as it will be referenced later, than here is the solution for an SSL http get, excluding the TLS_DHE_ cipher suites.

package org.example.security;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import org.apache.log4j.Logger;

public class SSLExcludeCipherConnectionHelper {

    private Logger logger = Logger.getLogger(SSLExcludeCipherConnectionHelper.class);

    private String[] exludedCipherSuites = {"_DHE_","_DH_"};

    private String trustCert = null;

    private TrustManagerFactory tmf;

    public void setExludedCipherSuites(String[] exludedCipherSuites) {
        this.exludedCipherSuites = exludedCipherSuites;
    }

    public SSLExcludeCipherConnectionHelper(String trustCert) {
        super();
        this.trustCert = trustCert;
        //Security.addProvider(new BouncyCastleProvider());
        try {
            this.initTrustManager();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void initTrustManager() throws Exception {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = new BufferedInputStream(new FileInputStream(trustCert));
        Certificate ca = null;
        try {
            ca = cf.generateCertificate(caInput);
            logger.debug("ca=" + ((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
        }

        // Create a KeyStore containing our trusted CAs
        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);
    }

    public String get(URL url) throws Exception {
        // Create an SSLContext that uses our TrustManager
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, tmf.getTrustManagers(), null);
        SSLParameters params = context.getSupportedSSLParameters();
        List<String> enabledCiphers = new ArrayList<String>();
        for (String cipher : params.getCipherSuites()) {
            boolean exclude = false;
            if (exludedCipherSuites != null) {
                for (int i=0; i<exludedCipherSuites.length && !exclude; i++) {
                    exclude = cipher.indexOf(exludedCipherSuites[i]) >= 0;
                }
            }
            if (!exclude) {
                enabledCiphers.add(cipher);
            }
        }
        String[] cArray = new String[enabledCiphers.size()];
        enabledCiphers.toArray(cArray);

        // Tell the URLConnection to use a SocketFactory from our SSLContext
        HttpsURLConnection urlConnection =
            (HttpsURLConnection)url.openConnection();
        SSLSocketFactory sf = context.getSocketFactory();
        sf = new DOSSLSocketFactory(sf, cArray);
        urlConnection.setSSLSocketFactory(sf);
        BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
        String inputLine;
        StringBuffer buffer = new StringBuffer();
        while ((inputLine = in.readLine()) != null) 
            buffer.append(inputLine);
        in.close();

        return buffer.toString();
    }

    private class DOSSLSocketFactory extends javax.net.ssl.SSLSocketFactory {

        private SSLSocketFactory sf = null;
        private String[] enabledCiphers = null;

        private DOSSLSocketFactory(SSLSocketFactory sf, String[] enabledCiphers) {
            super();
            this.sf = sf;
            this.enabledCiphers = enabledCiphers;
        }

        private Socket getSocketWithEnabledCiphers(Socket socket) {
            if (enabledCiphers != null && socket != null && socket instanceof SSLSocket)
                ((SSLSocket)socket).setEnabledCipherSuites(enabledCiphers);

            return socket;
        }

        @Override
        public Socket createSocket(Socket s, String host, int port,
                boolean autoClose) throws IOException {
            return getSocketWithEnabledCiphers(sf.createSocket(s, host, port, autoClose));
        }

        @Override
        public String[] getDefaultCipherSuites() {
            return sf.getDefaultCipherSuites();
        }

        @Override
        public String[] getSupportedCipherSuites() {
            if (enabledCiphers == null)
                return sf.getSupportedCipherSuites();
            else
                return enabledCiphers;
        }

        @Override
        public Socket createSocket(String host, int port) throws IOException,
                UnknownHostException {
            return getSocketWithEnabledCiphers(sf.createSocket(host, port));
        }

        @Override
        public Socket createSocket(InetAddress address, int port)
                throws IOException {
            return getSocketWithEnabledCiphers(sf.createSocket(address, port));
        }

        @Override
        public Socket createSocket(String host, int port, InetAddress localAddress,
                int localPort) throws IOException, UnknownHostException {
            return getSocketWithEnabledCiphers(sf.createSocket(host, port, localAddress, localPort));
        }

        @Override
        public Socket createSocket(InetAddress address, int port,
                InetAddress localaddress, int localport) throws IOException {
            return getSocketWithEnabledCiphers(sf.createSocket(address, port, localaddress, localport));
        }

    }
}

Finally here is how it is used (certFilePath if the path of the certificate saved from openssl):

try {
            URL url = new URL("https://www.example.org?q=somedata");            
            SSLExcludeCipherConnectionHelper sslExclHelper = new SSLExcludeCipherConnectionHelper(certFilePath);
            logger.debug(
                    sslExclHelper.get(url)
            );
        } catch (Exception ex) {
            ex.printStackTrace();
        }

@Ludovic Guillaume 2015-08-10 11:16:16

Just tested your solution. It's working as intended. Thanks. Actually, just adding jdk.tls.disabledAlgorithms=DHE, ECDHE in JDK_HOME/jre/lib/security/java.security also works and avoid all this code.

@stephan f 2015-10-26 13:46:01

Just disabling DHE worked for me: jdk.tls.disabledAlgorithms=DHE. Using 1.7.0_85-b15.

@Eric Na 2016-01-12 19:11:06

Added jdk.tls.disabledAlgorithms=DHE, ECDHE in JDK_HOME/jre/lib/security/java.security and worked fine! Thank you! Using 1.7.0_79

@kubanczyk 2016-06-08 13:36:19

Don't disable ECDHE. It's different than DHE and does not even use prime numbers.

@user1172490 2016-11-22 23:00:34

Can someone please tell me how i can get the 'certFilePath'. I've been stuck on this for a week. @Zsozso

@Lekkie 2013-05-22 08:29:27

If you are using jdk1.7.0_04, upgrade to jdk1.7.0_21. The problem has been fixed in that update.

@user2666524 2013-08-19 23:40:11

I just downloaded Java SE Development Kit 7u25, and according to the little program I wrote to determine the maximum supported DH size, it's still 1024.

@Sébastien Vanmechelen 2015-07-30 15:43:42

Problem still exists with JDK 1.7.0_25

@Elazaron 2015-08-25 09:07:17

updating jre worked for me .had 6.22 updated to 7.59 . problem solved.

@Shashank 2015-10-05 02:29:32

I am using JDK 1.7.0_79. Doesn't work for me

@dgoverde 2016-02-17 03:37:30

@Shashank - Upgrading to JDK 1.8.0_73 worked for me.

@mjomble 2011-11-17 21:02:40

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.

@clevertension 2014-12-17 01:51:52

it can't be work in my env when i replace the files from JCE

@Joerg 2015-03-16 17:17:20

have you done anyhting else? or just copied the 2 files into the folder?

@mjomble 2015-03-16 20:57:09

It's been a while but as far as I remember, that was all I needed to do. Apart from restarting any running Java processes afterwards.

@Peter Šály 2018-09-06 10:07:09

Does not work for me.

@sam 2011-07-28 16:30:49

The answer above is correct, but in terms of the workaround, I had problems with the BouncyCastle implementation when I set it as preferred provider:

java.lang.ArrayIndexOutOfBoundsException: 64
    at com.sun.crypto.provider.TlsPrfGenerator.expand(DashoA13*..)

This is also discussed in one forum thread I found, which doesn't mention a solution. http://www.javakb.com/Uwe/Forum.aspx/java-programmer/47512/TLS-problems

I found an alternative solution which works for my case, although I'm not at all happy with it. The solution is to set it so that the Diffie-Hellman algorithm is not available at all. Then, supposing the server supports an alternative algorithm, it will be selecting during normal negotiation. Obviously the downside of this is that if somebody somehow manages to find a server that only supports Diffie-Hellman at 1024 bits or less then this actually means it will not work where it used to work before.

Here is code which works given an SSLSocket (before you connect it):

List<String> limited = new LinkedList<String>();
for(String suite : ((SSLSocket)s).getEnabledCipherSuites())
{
    if(!suite.contains("_DHE_"))
    {
        limited.add(suite);
    }
}
((SSLSocket)s).setEnabledCipherSuites(limited.toArray(
    new String[limited.size()]));

Nasty.

@Vivin Paliath 2011-07-28 16:38:47

Sad that this is the only way :(. That ticket has been open since '07. Strange that nothing has been done about it in 4 years.

@Shashank 2015-10-05 02:28:43

I am new to java securities. Please help where should I write this piece of code?

@Gianluca Greco 2016-02-16 11:06:29

I tried every solution in this thread and this was the only one that worked with my ibm jvm (ibm-java-s390x-60).

Related Questions

Sponsored Content

8 Answered Questions

[SOLVED] Why is subtracting these two times (in 1927) giving a strange result?

  • 2011-07-27 08:15:58
  • Freewind
  • 568995 View
  • 6165 Score
  • 8 Answer
  • Tags:   java date timezone

12 Answered Questions

[SOLVED] Why does Java have transient fields?

  • 2009-05-26 12:11:36
  • Animesh
  • 599594 View
  • 1252 Score
  • 12 Answer
  • Tags:   java field transient

0 Answered Questions

Capturing client/server TLS version in Python requests

28 Answered Questions

2 Answered Questions

0 Answered Questions

14 Answered Questions

[SOLVED] Why does this code using random strings print "hello world"?

  • 2013-03-03 04:38:06
  • 0x56794E
  • 180348 View
  • 1624 Score
  • 14 Answer
  • Tags:   java string random

0 Answered Questions

MySQL - SSL - with TLS1.2 cipher AES256-SHA256 / DHE-RSA-AES256-SHA256

  • 2015-03-17 13:38:09
  • Bhushan Rane
  • 606 View
  • 1 Score
  • 0 Answer
  • Tags:   mysql ssl

1 Answered Questions

[SOLVED] Some clients accept SSL cert; others reject it

Sponsored Content