Implementing SSL in Java

Transport Layer Security (TLS) and its predecessor, Secure Sockets Layer (SSL), are cryptographic protocols that provide communication security over a network. TLS and SSL encrypt the segments of network connections at the Application Layer for the Transport Layer, using asymmetric cryptography for key exchange, symmetric encryption for confidentiality, and message authentication codes for message integrity.

My assignment in Cryptography and Network Security was to implement SSL, so I thought why not post some useful insights on how to implement TSL and SSL in Java.

TCP/UDP Primer
TCP and UDP are the primary methods of data transfer across the internet. TCP is a connection-orientated protocol, which guarantees order, delivery and contents. UDP does not provide these guarantees.

SSL Primer:
SSL/TLS is the system by which details are securely transferred across the internet. It’s required for payment systems and recommended for most other internet activity, especially when personal details are being transferred. Google is advocating it in their products (not just for payment and login, but site-wide). Facebook and Twitter have followed suit.

To use SSL you need a Certificate (typically X.509 standard), which is either a Trusted Root Certificate Authority itself, or signed by the issuer of the Trusted Root CA. Details are then transferred using Public Key Cryptography, using the public key contained in the Certificate. The Certificate also contains the validity period. Note that a number of Trusted Root CA’s are preloaded into operating systems by the OS developers.

Java Networking Primer
Java’s networking system originally consisted of a single package java.netThis package contains the networking tools most are familiar with:
DatagramPacket  – A single UDP message
DatagramSocket  – A socket (host and IP combination) for sending and recieving UDP packets
ServerSocket – A TCP server socket which accepts TCP connections.
Socket – A TCP socket which connects to a ServerSocket and to which bytes are written and read directly once connected.

Java’s SSL Implementation:
Java also provides a collection of SSL implementations, since Java 1.4. These are in the javax.net.ssl package and are as follows:

SSLServerSocket – Provides an SSL version of the Socket class -a TCP server socket which accepts SSL-secure TCP connections.
SSLServerSocketFactory – Generates SSLSockets and provides a lot of initial setup
SSLSocket – Provides an SSL version of the ServerSocket class – a TCP server socket which accepts TCP connections.
SSLSocketFactory – Generates SSLServerSockets and provides a lot of initial setup

The Blocking Problem (Enter NIO)
Unfortunately the method to read data from these (java.io.InputStream.read()) are blocking. So the only way to implement an application that handles lots of connections is to have lots of Threads, each of which blocked. For small applications this is tolerable. For applications with hundreds of clients, this isn’t realistic however – the overhead from 100s of threads is not useful.

There are some methods to tell it to stop always trying after reading for a bit if it finds. setSoTimeout() does this. However, if you have a hundred clients, it’s not a workable solution as you have to iterate round a set of  sockets continously, waiting for each expiry. In reality you need multiple threads just to read all the Sockets with enough regularity (the shortest timer is 1ms so if you have 1 thread and 100 clients, you can try reading 10 times a second. Finally you are continously throwing and catching Exceptions which should indicate there’s a design model problem.

So in the same Java 1.4 release, they released the N/IO (New Input/Output) package: java.nio which use Buffers, Channels and Selectors. However only the following Networking Channels were available
java.nio.channels.SocketChannel
java.nio.channels.ServerSocketChannel

However, there were no SSL implementations.

The Solution (Enter SSLEngine)

In Java 1.5 / aka Java 5, Sun decided that the best course was to simply allow access to more of the underlying SSL system. Hence in 1.5 the SSL Engine class was made available.

The problem is that it’s not really trivial to combine the non-blocking SSLEngine with the SocketChannel system. During this post I’ll hash out one possible implementation:

We start with SSLEngine. To create an SSLEngine, according to the javadoc, we must call

SSLContext.createSSLEngine();

So this means we need an SSLContext (and it also has to be initalised):

Hence:

SSLContext sslc = SSLContext.getDefault();
sslc.init();
SSLEngine ssle = SSLContext.createSSLEngine();

All of this assumes we’re happy with the defaults for: Protocol, Provider, KeyManager, TrustManager and SecureRandom. Given that we’re not doing anything revolutionary in those, let’s leave them.

Next we need to configure it for Client mode.

ssle.setUseClientMode(true);

Once we’ve read data in, similar to the following:

ByteBuffer read = ByteBuffer.allocate(48);
int bytesRead = socketChannel.read(buf);

Then we have to run the SSLEngine on it

ByteBuffer toApp = ByteBuffer.allocate(48)
SSLEngineResult res = ssle.unwrap(read,toApp);

Finally we process our message, with the channel for reference purposes

processMessage(this,socketChannel,toApp.toArray);

This still needs considerable clarification –  it appears you need an SSLEngine instance for every connection – which seems OTT and collecting all of it together in a couple of classes is quite a bit off. I’ll follow up with this later when I can get the last few details sorted.

Advertisements