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 »

WKBReader: ParseException: Unknown WKB type x

I’m using the Java API JTS Topology Suite to do spatial operations. To convert a byte array into a Geometry object the following helper class was used:

public class JTSHelper {
	static WKBReader wkbReader = new WKBReader();

	public static Geometry bytesToGeometry(byte geometryBytes[]) throws ParseException {
		return wkbReader.read(geometryBytes);
	}
}

This seemed to work well, but in the logfile we saw intermittent failures caused by this class:
ParseException: Unknown WKB type 139
ParseException: Unknown WKB type 0
ParseException: Unknown WKB type 17

The WKB type numbers were always different, but when checking the incoming byte arrays everything seems to be OK.

With apache benchmark tool the failures could be reproduced when increasing the number of concurrent requests:
ab -n 1000 -c 10 http://localhost:8080/project/test-action

A look at JavaDoc of WKBReader shows that this class is not thread-safe. Therefore the solution is to put WKBReader in ThreadLocal:

public class JTSHelper {
	static ThreadLocal<WKBReader> wkbReader	= new ThreadLocal<WKBReader>() {
		protected WKBReader initialValue() { return new WKBReader(); };
	};

	public static Geometry bytesToGeometry(byte geometryBytes[]) throws ParseException {
		WKBReader reader = wkbReader.get();
		return reader.read(geometryBytes);
	}
}

Versions: JTS 1.8, JDK 5

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