Skip to content

Mutual TLS

Mutual TLS (mTLS) is a security mechanism that extends standard TLS by requiring both the server and the client device to authenticate each other during connection establishment.

Use this feature when your infrastructure requires client certificate authentication in addition to standard server certificate validation.

To configure mTLS on the server side, follow the Enabling mTLS Guide.

Currently, this feature is supported only on Android.

Generating Certificates

The example below shows how to generate the certificates required for mTLS testing on Android.

# Generate the CA private key
openssl genrsa -out ca.key 2048

# Generate a self-signed CA certificate
openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 \
  -out ca.crt -subj "/O=TestCA/CN=Test Root CA"

# Generate the server private key
openssl genrsa -out server.key 2048

# Generate a certificate signing request (CSR) for the server
openssl req -new -key server.key -out server.csr \
  -subj "/O=TestServer/CN=localhost"

# Sign the server certificate with the CA
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out server.crt -days 365 -sha256

# Generate the client private key
openssl genrsa -out client.key 2048

# Generate a certificate signing request (CSR) for the client
openssl req -new -key client.key -out client.csr \
  -subj "/O=TestClient/CN=test-client"

# Sign the client certificate with the CA
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out client.crt -days 365 -sha256

# Export the client certificate and private key to PKCS#12
openssl pkcs12 -export -out client.p12 \
  -inkey client.key -in client.crt -certfile ca.crt \
  -name "client"

# Export the CA certificate to a PKCS#12 truststore
openssl pkcs12 -export -nokeys -out client_truststore.p12 \
  -in ca.crt -name "ca"

Configuring mTLS

The following examples configure the SSL context for HTTPS connections using client.p12 as the client keystore and client_truststore.p12 as the truststore:

import java.io.FileInputStream
import java.security.KeyStore
import java.security.SecureRandom
import javax.net.ssl.HttpsURLConnection
import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory
fun main() {
    // --- Configuration ---
    val clientP12Path = "path/to/client.p12"
    val clientP12Password = "client-password"
    val trustStoreP12Path = "path/to/client_truststore.p12"
    val trustStorePassword = "truststore-password"
    val clientKeyStore = KeyStore.getInstance("PKCS12").apply {
        FileInputStream(clientP12Path).use { load(it, clientP12Password.toCharArray()) }
    }
    val trustStore = KeyStore.getInstance("PKCS12").apply {
        FileInputStream(trustStoreP12Path).use { load(it, trustStorePassword.toCharArray()) }
    }
    val keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()).apply {
        init(clientKeyStore, clientP12Password.toCharArray())
    }
    val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()).apply {
        init(trustStore)
    }
    val sslContext = SSLContext.getInstance("TLS").apply {
        init(
            keyManagerFactory.keyManagers,
            trustManagerFactory.trustManagers,
            SecureRandom()
        )
    }
    HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.socketFactory)
}
import javax.net.ssl.*;
import java.io.FileInputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.security.KeyStore;
import java.security.SecureRandom;

public class MtlsHttpClient {

    public static void main(String[] args) throws Exception {
        // --- Configuration ---
        String clientP12Path = "path/to/client.p12";
        String clientP12Password = "client-password";
        String trustStoreP12Path = "path/to/client_truststore.p12";
        String trustStorePassword = "truststore-password";
        String targetUrl = "https://api.example.com/secure-endpoint";

        // Load client keystore and truststore
        KeyStore clientKeyStore = KeyStore.getInstance("PKCS12");
        try (FileInputStream clientKeyStoreStream = new FileInputStream(clientP12Path)) {
            clientKeyStore.load(clientKeyStoreStream, clientP12Password.toCharArray());
        }

        KeyStore trustStore = KeyStore.getInstance("PKCS12");
        try (FileInputStream trustStoreStream = new FileInputStream(trustStoreP12Path)) {
            trustStore.load(trustStoreStream, trustStorePassword.toCharArray());
        }

        // Initialize KeyManager and TrustManager factories
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(clientKeyStore, clientP12Password.toCharArray());

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trustStore);

        // Create SSLContext
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());

        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
    }
}