You are currently viewing Creating a Java Client-Server Application with mTLS

Creating a Java Client-Server Application with mTLS

  • Post author:
  • Post category:Java
  • Post comments:0 Comments
  • Post last modified:May 3, 2024

Introduction

In the realm of secure communication over networks, Mutual Transport Layer Security (mTLS) stands out as a robust protocol for ensuring both authentication and encryption between client and server. Building a Java client-server application with mTLS not only enhances security but also establishes a trustworthy connection where both parties can verify each other’s identities.

In this tutorial, we will embark on a journey to create a Java client-server application leveraging the power of mTLS. We’ll delve into the intricacies of setting up a secure communication channel, where both the client and server authenticate each other using digital certificates, and data exchanged between them remains encrypted throughout the transmission.

Through step-by-step instructions, we’ll explore how to generate and manage digital certificates, configure the Java server and client to enable mTLS, and establish a secure channel for communication. By the end of this tutorial, you’ll have a deep understanding of how to implement mTLS in Java applications, equipping you with the knowledge to build secure and reliable client-server architectures.

Let’s embark on this journey to harness the power of mTLS and fortify the communication channels of our Java applications.

Step 1: Generate Certificate Authority (CA)

  1. Create a CA Key and Certificate:
    First, generate a private key for the Certificate Authority (CA) and then create a self-signed certificate for the CA.
openssl genrsa -out ca-key.pem 2048
openssl req -new -x509 -key ca-key.pem -out ca-cert.pem -days 365

Step 2: Create Server Certificate

  1. Generate Server Key and CSR:
    Next, create a private key and a Certificate Signing Request (CSR) for the server.
   openssl genrsa -out server-key.pem 2048
   openssl req -new -key server-key.pem -out server-csr.pem
  1. Sign the Server Certificate with CA:
    Use the CA’s private key to sign the server’s CSR, creating the server certificate.
   openssl x509 -req -in server-csr.pem -CA ca-cert.pem -CAkey ca-key.pem -out server-cert.pem -days 365 -CAcreateserial

Step 3: Create Client Certificate

  1. Generate Client Key and CSR:
    Similarly, create a private key and CSR for the client.
   openssl genrsa -out client-key.pem 2048
   openssl req -new -key client-key.pem -out client-csr.pem
  1. Sign the Client Certificate with CA:
    Sign the client’s CSR with the CA to create the client certificate.
   openssl x509 -req -in client-csr.pem -CA ca-cert.pem -CAkey ca-key.pem -out client-cert.pem -days 365 -CAcreateserial

Now that we have the necessary certificates, let’s create the Java programs for the server and client.

Step 4: Java Server Program

  1. Java Server Code:
    Create a Java server that loads the server certificate and private key, and sets up an HTTPS server with mutual TLS.
   import javax.net.ssl.*;
   import java.io.FileInputStream;
   import java.io.IOException;
   import java.security.*;
   import java.security.cert.CertificateException;

   public class MTLSHttpServer {
       public static void main(String[] args) throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
           String keystorePath = "server-keystore.jks";
           char[] keystorePass = "password".toCharArray();

           KeyStore keyStore = KeyStore.getInstance("JKS");
           keyStore.load(new FileInputStream(keystorePath), keystorePass);

           KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
           kmf.init(keyStore, keystorePass);

           SSLContext sslContext = SSLContext.getInstance("TLS");
           sslContext.init(kmf.getKeyManagers(), null, null);

           HttpsServer server = HttpsServer.create(new InetSocketAddress(8443), 0);
           server.setHttpsConfigurator(new HttpsConfigurator(sslContext) {
               public void configure(HttpsParameters params) {
                   try {
                       SSLContext context = SSLContext.getDefault();
                       SSLEngine engine = context.createSSLEngine();
                       params.setNeedClientAuth(true);
                       params.setCipherSuites(engine.getEnabledCipherSuites());
                       params.setProtocols(engine.getEnabledProtocols());

                       SSLParameters sslParameters = context.getDefaultSSLParameters();
                       params.setSSLParameters(sslParameters);
                   } catch (Exception ex) {
                       System.out.println("Failed to create HTTPS port");
                   }
               }
           });

           server.createContext("/", (exchange -> {
               String response = "Hello, this is a secure server!";
               exchange.sendResponseHeaders(200, response.length());
               exchange.getResponseBody().write(response.getBytes());
               exchange.getResponseBody().close();
           }));

           server.start();
           System.out.println("Server running on port 8443");
       }
   }

Step 5: Java Client Program

  1. Java Client Code:
    Now, create a Java client that loads the client certificate and key, and performs an HTTPS request to the server with mutual TLS.
   import javax.net.ssl.*;
   import java.io.FileInputStream;
   import java.io.IOException;
   import java.net.URL;
   import java.security.*;
   import java.security.cert.CertificateException;

   public class MTLSHttpClient {
       public static void main(String[] args) throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
           String keystorePath = "client-keystore.jks";
           char[] keystorePass = "password".toCharArray();

           KeyStore keyStore = KeyStore.getInstance("JKS");
           keyStore.load(new FileInputStream(keystorePath), keystorePass);

           KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
           kmf.init(keyStore, keystorePass);

           SSLContext sslContext = SSLContext.getInstance("TLS");
           sslContext.init(kmf.getKeyManagers(), null, null);

           HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

           URL url = new URL("https://localhost:8443/");
           HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

           conn.setRequestMethod("GET");
           conn.setRequestProperty("Accept", "application/json");

           int responseCode = conn.getResponseCode();
           System.out.println("Response Code: " + responseCode);

           if (responseCode == HttpURLConnection.HTTP_OK) {
               BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
               String inputLine;
               StringBuilder response = new StringBuilder();

               while ((inputLine = in.readLine()) != null) {
                   response.append(inputLine);
               }
               in.close();

               System.out.println("Response: " + response.toString());
           } else {
               System.out.println("Request failed");
           }
       }
   }

Step 6: Run the Server and Client

  1. Run the Server:
    Compile and run the MTLSHttpServer program. Make sure server-cert.pem, server-key.pem, and ca-cert.pem are in the same directory, or update the paths in the server code.
   javac MTLSHttpServer.java
   java MTLSHttpServer
  1. Run the Client:
    Compile and run the MTLSHttpClient program. Ensure client-cert.pem, client-key.pem, and ca-cert.pem are in the same directory, or update the paths in the client code.
   javac MTLSHttpClient.java
   java MTLSHttpClient

Notes:

  • Make sure to adjust paths and filenames as per your actual file locations and names.
  • You’ll need the Java KeyStore (JKS) files for both server and client, which can be created from the PEM files using keytool.
  • This example uses Java’s built-in `HttpsServer

This setup will allow the Java client and server to communicate over HTTPS with mutual TLS authentication using the generated certificates.

Leave a Reply