Java SSL: unable to find valid certification path to requested target

While accessing a webservice over SSL, I got an SSLHandshakeException: PKIX path building failed. This is normally due to problems with the SSL certificate, so I tested the certifcate directly:

import java.io.IOException;
import java.net.UnknownHostException;
import java.security.cert.Certificate;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

public class CertTest {
	public static void main(String[] args) throws UnknownHostException, IOException {
		int port = 443;
		String hostname = "webservice.com";

        // get debug information of SSL
        System.setProperty("javax.net.debug", "ssl");

	    SSLSocketFactory factory = HttpsURLConnection.getDefaultSSLSocketFactory();
	    SSLSocket socket = (SSLSocket) factory.createSocket(hostname, port);

	    socket.startHandshake();

	    System.out.println("===============");

	    Certificate[] serverCerts = socket.getSession().getPeerCertificates();
	    System.out.println("number of found certificates: " + serverCerts.length);
	    System.out.println("===============");
	    for (Certificate certificate : serverCerts) {
	    	System.out.println(certificate.getPublicKey());
			System.out.println(certificate);
			System.out.println("===============");
		}

	    socket.close();
	}
}

With CertTest I got the same error:

Exception in thread "main" 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
	at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1584)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:848)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
	at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
	at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:877)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1089)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1116)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1100)
	at de.raumobil.apcoa.ws.CertTest.main(CertTest.java:20)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:221)
	at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:145)
	at sun.security.validator.Validator.validate(Validator.java:203)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
	at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)
	... 8 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:236)
	at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:194)
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:216)
	... 13 more

The exception indicates that the key chain of the certificate is broken or that it’s simply a self signed certifcate.
To check that you can use: SSL Checker.

If In both cases you can create a keystore and import this certificate (you can download/export it with your browser) as trusted certificate:
keytool -import -trustcacerts -file webservice.com.pem -alias webservice -keystore myKeystore

In the CertTest you have to add the following lines to use the keystore:
System.setProperty("javax.net.ssl.trustStore","myKeystore");
System.setProperty("javax.net.ssl.trustStorePassword","myPassword");

If the SSL Checker said that everything is fine: “The certificate should be trusted by all major web browsers (all the correct intermediate certificates are installed).”, you propably ran in the Java bug Presence of a critical subjectAltName causes JSSE’s SunX509 to fail trusted checks. This Bug was fixed in Java 6 Update 10. So with updating to the current version everything should work well.

Resources

Posted in Java. Tags: , . Leave a Comment »

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: