I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we’ll introduce SSL and explore how we can use it in Java using JSSE (Java Secure Socket Extension) API.

2. Introduction

Simply put, the Secured Socket Layer (SSL) enables a secured connection between two parties, usually clients and servers.

SSL provisions a secure channel between two devices operating over a network connection. One usual example for SSL is to enable secure communications between web browsers and web servers.

In this specific case, web browsers will use HTTPS (S standing for Secured) connections to access the resources supplied by distinct web servers.

SSL is necessary to support the three main information security principles:

  • Encryption: protect data transmissions between parties
  • Authentication: ensure the server we connect to is indeed the proper server
  • Data integrity: guarantee that the requested data is what is effectively delivered

Java provides several security-based APIs that help out developers to establish secure connections with the client to receive and send messages in an encrypted format:

  • Java Secured-Socket Extension (JSSE)
  • Java Cryptography Architecture (JCA)
  • Java Cryptographic Extension (JCE)

In the next sections, we’ll introduce the Secure Socket Extension that Java uses to enable secure communication.

3. JSSE API

The Java security APIs make use of the Factory design pattern extensively.

In fact, everything is instantiated using a factory in JSSE.

3.1. SSLSocketFactory

The javax.net.ssl.SSLSocketFactory is used for creating SSLSocket objects.

This class contains three groups of APIs.

The first group consists of a single static getDefault() method used to retrieve the default instance which, in turn, can create SSLSocket instances.

The second group consists of five methods that can be used for creating SSLSocket instances:

  • Socket createSocket(String host, int port)
  • Socket createSocket(String host, int port, InetAddress clientHost, int clientPort)
  • Socket createSocket(InetAddress host, int port)
  • Socket createSocket(InetAddress host, int port, InetAddress clientHost, int clientPort)
  • Socket createSocket(Socket socket, String host, int port, boolean autoClose)

We can use this class directly by obtaining the default instance or by using a javax.net.ssl.SSLContext object which contains methods to get an SSLSocketFactory instance.

3.2. SSLSocket

This class extends the Socket class and provides secure socket. Such sockets are normal stream sockets.

In addition, they add a layer of security protections over the underlying network transport protocol.

SSLSocket instances construct an SSL connection to a named host at a specified port.

This allows binding the client side of the connection to a given address and port.

3.3. SSLServerSocketFactory

The SSLServerSocketFactory class is quite similar to SSLSocketFactory with the difference that it creates SSLServerSocket instances in place of SSLSocket instances.

By similarity, the methods are called createServerSocket as analogous to SSLSocketFactory class.

3.4. SSLServerSocket

The SSLServerSocket class is analogous to the SSLSocket class. The methods on SSLServerSocket class are a subset of the SSLSocket class methods. They act on the opposite side of an SSL connection

4. SSL Example

Let’s provide an example of how we can create a secured connection to a server:

String host = getHost(...);
Integer port = getPort(...);
SSLSocketFactory sslsocketfactory = SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory
  .createSocket(host, port);
InputStream in = sslsocket.getInputStream();
OutputStream out = sslsocket.getOutputStream();

out.write(1);
while (in.available() > 0) {
    System.out.print(in.read());
}

System.out.println("Secured connection performed successfully");

In case we get the error “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 while establishing the SSL connection”, it indicates that we don’t have the public certificate of the server which we’re trying to connect in the Java truststore.

The truststore is the file containing trusted certificates that Java uses to validate secured connections.

In order to sort this problem out, we have several options:

  • add the public certificate of the server to the default cacerts truststore used by Java. while initiating the SSL connection
  • Set the javax.net.ssl.trustStore environment variable to point to the truststore file so that the application can pick up that file which contains the public certificate of the server we are connecting to.

The steps to install a new certificate into the Java default truststore are:

  1. extract cert from server: openssl s_client -connect server:443
  2. import certificate into truststore using keytool: keytool -import -alias alias.server.com -keystore $JAVA_HOME/jre/lib/security/cacerts

Once we have done this, we should be able to run the example again and obtain the Secured connection performed successfully message.

5. Conclusion

In this article, we introduced SSL and JSSE API, which implements SSL for Java. By using SSL and JSSE, we can make our Java applications and the communications between applications and inside the application safer.

As always, the code presented in this article is available over on Github.

I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE LESSONS