0
votes

We have a self signed certificate in development environment of our legacy application. Application is accessible (with cert error - This CA Root certificate is not trusted because it is not in the Trusted Root Certification Authorities store.) from browser but when accessed from java code (using HttpsURLConnection), it gives SSLHandshakeException.

After going through many stackoverflow questions (including telling java to accept self-signed ssl certificate) and some articles available on internet, I followed below steps but no any luck yet:

  1. Exported certificate from browser (mycert.cer)
  2. Imported this mycert.cer in JVM truststore by using command: keytool -import -alias myApp -file mycert.cer -keystore cacerts -storepass changeit

After running this, checked if it was successfully added using keytool -list -keystore cacerts

Even after adding this certificate in java truststore, https from java code gives me javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Any pointers on this are much appreciated.

Please note: This self -signed certificate is created long back and we dont have much details about how it was created.

Some more details: Java version - Java 1.6 Complete error trace:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1822)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1004)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1188)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1215)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1199)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:318)

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1514)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1508)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1162)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)

Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1822)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1004)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1188)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1215)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1199)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:318)

    ... 1 more
2
A handshake exception could be anything, like mismatch of protocol versions, ciphers... Please provide debug output, packet capture, information about the Java version used etc.Steffen Ullrich
Hi Steffen, I am new to SSL, please could you let me know how can I find packet capture ? java version is 1.6nshweta

2 Answers

1
votes

It would have been better if you post the SSLHandshakeException stack trace. However, If you are getting some thing like this:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

then please have a look to the below URLs. These will be useful:

a. http://www.mkyong.com/webservices/jax-ws/suncertpathbuilderexception-unable-to-find-valid-certification-path-to-requested-target/

b. http://code.google.com/p/java-use-examples/source/browse/trunk/src/com/aw/ad/util/InstallCert.java

If you are getting some thing like this:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present

Use -ext san=ip:<IP Address>, san (Subject Alternative Name) while creating the keystore. This is supported from JDK 1.7 onwards.

0
votes

Your best bet is probably to grab wireshark and verify the SSL alert value and go from there. This is probably an alert value 40, which would mean you didn't find compatible protocols. Either the server requires an SSL/TLS version that the client can't support, or they don't have compatible cipher suites.