Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JDK11 HttpClient mutual tls

I'm looking to use the new HttpClient provided in java 11. It's not clear how to do mutual TLS (2 way auth, where both client and server present a certificate.)

Could someone provide an example of mutual TLS with HttpClient?

like image 458
fafrd Avatar asked May 09 '26 18:05

fafrd


1 Answers

Figured it out. Create an HttpClient, then pass in SSLContext and SSLParameters objects.

Load cert/key into SSLContext:

 // cert+key data. assuming X509 pem format
final byte[] publicData = your_cert_data; // -----BEGIN CERTIFICATE----- ...
final byte[] privateData = your_key_data; // -----BEGIN PRIVATE KEY----- ...

// parse certificate
final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
final Collection<? extends Certificate> chain = certificateFactory.generateCertificates(
        new ByteArrayInputStream(publicData));

LOG.info("Successfully loaded the client cert certificate chain {}", String.join(" -> ", chain.stream().map(certificate -> {
        if (certificate instanceof X509Certificate x509Cert) {
            return x509Cert.getSubjectX500Principal().toString();
        } else {
            return certificate.getType();
        }
    }).toList()));

// parse key
final Key key = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateData));

// place cert+key into KeyStore
KeyStore clientKeyStore = KeyStore.getInstance("jks");
final char[] pwdChars = KEYSTORE_PASSWORD.toCharArray(); // use a random string, like from java.security.SecureRandom
clientKeyStore.load(null, null);
clientKeyStore.setKeyEntry(YOUR_SERVICE_NAME, key, pwdChars, chain.toArray(new Certificate[0]));

// initialize KeyManagerFactory
KeyManagerFactory keyMgrFactory = KeyManagerFactory.getInstance("SunX509");
keyMgrFactory.init(clientKeyStore, pwdChars);

// populate SSLContext with key manager
SSLContext sslCtx = SSLContext.getInstance("TLSv1.2");
sslCtx.init(keyMgrFactory.getKeyManagers(), null, null);

Create ssl parameters, set needClientAuth to true:

SSLParameters sslParam = new SSLParameters();
sslParam.setNeedClientAuth(true);

finally, create the HttpClient:

HttpClient client = HttpClient.newBuilder()
    .sslContext(sslCtx)
    .sslParameters(sslParam)
    .build();
like image 70
fafrd Avatar answered May 12 '26 09:05

fafrd



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!