Java SSL: How to accept a self-signed certificate

I’ve been working on a RESTful API for use on computers and mobile devices. I have a JUnit test case that connects to the URLs and reads the responses. Given the nature of the data being transferred back and forth, I enabled SSL on the web server using a self-signed certificate I generated using Java’s keytool.

keytool -genkey -alias <hostname> -keyalg RSA

This is where my problems began. My test case is using HTTP, so I needed to refactor it to use the HTTPS protocol. Unbeknownst to me, accepting SSL connections from self-signed certificates is non-trivial, especially if you want to do it right. There is copious advice on the inter-web about how to accept any certificate. I’m not keen on that approach; therefore, I set out to find the correct way.

Without a decent Java security reference handy, I surfed the internet for answers. I found partial code snippets on stackoverflow and Example Depot. In a nutshell, I found that you need an instance of a SSLSocketFactory to set in a HttpsURLConnection. Here’s how:

// Load the keystore in the user's home directory
File file = new File(System.getProperty("user.home") + File.separatorChar + ".keystore");
FileInputStream fis = null;
KeyStore keyStore = null;

fis = new FileInputStream(file);
keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(fis, keystorePassword.toCharArray());

TrustManagerFactory tmf;

tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);

//Get an instance of the socket factory
SSLSocketFactory sslFactory = ctx.getSocketFactory();

HttpsURLConnection connection = null;
url = new URL(newURLString);

connection = (HttpsURLConnection)url.openConnection();

//set the socket factory in the connection
connection.setSSLSocketFactory(sslFactory);

//...

Tip: Remember the alias created in the keytool must be the hostname of the server. Otherwise, an exception will be thrown on the client:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching <alias> found
Advertisements
Java SSL: How to accept a self-signed certificate

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 )

Google+ photo

You are commenting using your Google+ 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 )

Connecting to %s