tags:

views:

1582

answers:

3

I have to write a Java Client to connect to an SSL server. The server uses openssl certificate, and is configured to do Client Auth.

I can't seem to locate any useful resources online that can help me (who doesn't know anything about openssl and much about SSL) to understand who to go about implementing my Client Side.

Help!

A: 

You could use httpclient. Have a look at this SSL guide.

kgiannakakis
+1  A: 

Java includes SSL support in the standard API. Have a look at these classes in the 1.5.0 javadoc:

SSLSocket if you're doing the comms logic yourself.

HttpsURLConnection if the server side speaks HTTP

Cogsy
+3  A: 

The twist here is that you are using client authentication, so you need a private key and a certificate to identify yourself. You provide this to JSSE by specifying KeyManagers when you initialize an SSLContext.

Customizable Setup

Following are the basic steps. The JSSE API was significantly improved in Java 6, but I'll stick with Java 5, in case you're stuck on that version.

KeyStore tks = KeyStore.getInstance(KeyStore.getDefaultType());
tks.load(...); /* Load the trust key store with root CAs. */
TrustManagerFactory tmf = 
  TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(tks);
KeyStore iks = KeyStore.getInstance(KeyStore.getDefaultType());
iks.load(...); /* Load the identity key store with your key/cert. */
KeyManagerFactory kmf = 
  KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(iks, password);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SocketFactory factory = ctx.getSocketFactory();
Socket socket = factory.createSocket(host, port);

System Configuration

An alternative "zero-config" scenario can be used when using the SunJSSE provider. I believe many other providers (like IBM) have followed the same pattern and will work as well. The mechanism uses system properties, and is described in detail by the JSSE Reference Guide.

For client authentication, the important properties are javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword. The values should be the path to the user's key store and the password for that key store's "key entries", respectively.

When using these properties, you can create a new SSLSocket that supports client authentication like this:

SocketFactory factory = SSLSocketFactory.getDefault();
Socket socket = factory.createSocket(host, port);

Since you are using the "default" SSLSocketFactory, which depends on the system-wide properties, all sockets created in the JVM will authenticate with the same certificate. If you need more control than that, you have to use the "Customizable Setup" above.

erickson
I'm currently trying to get your code to work, but have some questions: 1. KeyStore.getDefaultAlgorithm() doesn't seem to exist. 2. Is there some (any) way of having a zero-configuration method of getting/generating the key stores? At the moment, I'm stymied by the "..." inside the calls to load.
Zarkonnen
Sorry, the "KeyStore" there was wrong; I fixed that. As for initializing the key stores, yes, there is a method that uses system properties, with default values for the important properties. I'll update my answer with that.
erickson
If you need help actually creating a key pair, getting a certificate, and getting them all into a KeyStore, please ask.
erickson