Mutual Transport Layer Security

Gauraw Singh
6 min readApr 30, 2020

In this article, we will under MTLS and how it can be used to secure and encrypt the data in transit. We will also see how it can be used as a mutual authentication mechanism between two applications.

“Enabling HTTPS on the server is called one-way TLS, but if client has to identify itself its called two-way TLS”

We will be using spring boot for demonstrating the example and understand the whole concept in detail.

Securing Transport Layer

We will understand the concept using Spring boot. Let's understand two common types of certificates used in the industry and how we can generate it.

Let understand first the difference between Truststore and Keystore. Truststore is used to store certificates from trusted Certificate authorities (CA) which are used to verify the certificate presented by Server in SSL connection. While Keystore is used to store private keys and own identity certificate which applications will present to other parties.

Java comes with a tool called keytool which can be used to generate the certificate. There are commonly two types of certificate formats JKS and PKCS. JKS is a format specific to Java, while PCKS is a standardized and language-neutral way of storing encrypted private keys and certificates.

Let's start with how we can establish transport layer security for Spring boot application.

1: Generate Spring boot application with https://start.spring.io/ and just add web dependency.

Click on generate and import the project in your IDE.

We will develop an endpoint and GET /customers which will return the name of the customer and we will use the curl command to access the endpoint.

let's

call the endpoint with curl, it will return a successful response

Now let's secure our application for TLS

1: We will use Java distribution to generate a key pair and store it in keystore.jks file. The file is also known as Keystore.

keytool -genkey -alias example -keyalg RSA -keysize 4096 -validity 3650 -dname "CN=localhost, OU=bar, O=xyz, L=sjc, S=ca, C=in" -keypass springboot -keystore keystore.jks -storeType jks -storepass springboot

Let’s understand arguments given to the keytool command

  • alias: is used to identify the generated keys stored in the Keystore.
  • validity: number of days for which the keys are valid.
  • keysize: specify the length of the generated keys.
  • genkey: is an option that tells keytool to generate new keys.
  • keyalg: specify the algorithm which is used for generating keys.

The certificate which is generated is called a self-signed certificate because it was not generated by the trusted authority.

2: Now we have to import the certificate in our application, copy the keystore.jks in your resources folder or even you can give an external path.

now configure the properties in the application.properties file

and if you will notice your server would have started with https. Now lets again hit the API using the curl command

Exception

if you call HTTP endpoint it will throw an error. If you call https endpoint it will return you success. Kindly note as we are using a self-signed certificate either we have to call the API with -k option or with the — cacert options.

How we can fetch the public certificate from the keystore.jks

keytool -export -file ca.crt -alias example -rfc -keystore keystore.jks -storePass springboot

using the ca.crt which we generated you can call endpoint without -k options

now let's see how we can protect the GET /customers endpoint using Mutual TLS. Consider a scenario there are two applications application A which contains endpoint GET /customers and there is another application B that contains endpoint GET /info. Info endpoint consumes GET /customer endpoint. As we have already implemented application A.

Mutual TLS

Mutual TLS enabled service to service-based authentication.

1: Implement service B which consumes service A.

2: Create another application B with endpoint GET /info which calls GET /customers using rest template.

// Code will come here

3: Now let's generate a certificate for application B also which is a client of application A

keytool -genkey -alias example1 -keyalg RSA -keysize 4096 -validity 3650 -dname "CN=localhost, OU=bar, O=xyz, L=sjc, S=ca, C=in" -keypass springboot -keystore keystore1.jks -storeType jks -storepass springboot

4: Import the generated certificate in application B, as we did in application A. Copy the keystore1.jks into the resource folder and add the properties in application.properties.

server.port=9090server.ssl.key-store=keystore1.jksserver.ssl.key-store-password=springbootserver.ssl.key-alias=example1

5: Now you have to export the certificate of the server(application A) and then createTruststore for the client and import the certificate in it.

export server certificate using keytool. keystore.jks was application A certificate which has GET /customers endpoint.

keytool -exportcert -keystore keystore.jks -storepass springboot -alias example -rfc -file server.cer

now create the Truststore for the client (application B)

keytool -keystore truststore1.jks -importcert -file server.cer -alias example -storepass springboot

we need to tell the client ( application B) also regarding the Truststore to use. Update the application.properties for Truststore properties

server.port=9090server.ssl.key-store=keystore1.jksserver.ssl.key-store-password=springbootserver.ssl.key-alias=example1server.ssl.trust-store=truststore1.jksserver.ssl.trust-store-password=springboot

6: Now similarly export the certificate of the client ( Application B) and create Truststore for the server (application A)

# Client certificate exported in client.cerkeytool -exportcert -keystore keystore1.jks -storepass springboot -alias example1 -rfc -file client.cer

create Truststore for the server ( application A)

# Truststore created with client certificatekeytool -keystore truststore.jks -importcert -file client.cer -alias example1 -storepass springboot

update the server application.propeties with server Truststore

server.port=8080server.ssl.key-store=keystore.jksserver.ssl.key-store-password=springbootserver.ssl.key-alias=exampleserver.ssl.trust-store=truststore.jksserver.ssl.trust-store-password=springbootserver.ssl.client-auth=need

Now we are ready for the demo

If you call the server URL directly let's see if we get any error.

curl -i -k https://localhost:8080/customers

the server will not allow the request which is not coming from the Trusted store. You will get the bad certificate exception as shown below.

But if you hit the GET /customers by GET /info you will get success.

Kindly do share your feedbacks at “georgian3590@gmail.com” Thank you!

--

--