Wednesday, September 8, 2010

Java SSL Connections

A while back I wrote a post on how to use the apache web client to connect to an SSL server without a globally recognized certificate.  The easy way is just to import the certificate authority certificate into your cacerts file in $JAVA_HOME/jre/lib/security but in some cases you can’t do this, so I showed how I created a custom socket factory and then registered the socket factory with the Protocol class.

While trying to get an XHTML rendering library to work today, I had an issue with untrusted certificates that I needed to get working, but since the library wasn’t using the apache web client, I was a bit stuck.  As it turns out, there is much lower level you can get to to make this work:

TrustManagerFactory tmFactory = 
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream is = ClassLoader.getSystemResourceAsStream("my.truststore");
trustStore.load(is, "password".toCharArray());
TrustManager[] tm = tmFactory.getTrustManagers();
KeyManagerFactory kmFactory = 
KeyStore keyStore = KeyStore.getInstance("pkcs12");
InputStream kis = ClassLoader.getSystemResourceAsStream("keystore.p12");
keyStore.load(kis, "password".toCharArray());
KeyManager[] km = kmFactory.getKeyManagers();
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(km, tm, null);

I like this way a lot better because it uses classes only from the package and work perfectly for all java based network connections.  All you have to do is create your keystore/truststore files and make them available to this code somewhere in the classpath.