0

I am using modified version below code for SSL client certificate authentication. It worked in JDK 8, recently I changed to JDK 11, now with same code authentication is failing. If I switch to JDK 8 it works. Any changes in JDK 11 to handle the SSL client certificate authentication? Any tips to make this code work JDK will be helpful.

package org.example.test;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.junit.Test;

import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;

/**
 * Demonstrate connecting to a server secured with client-side SSL certificates.
 */
public class ConnectIT {

    /**
     * Path to your client-side SSL certificate in the PKCS12 format, as generated by OpenSSL.
     */
    final String KEY_STORE_PATH = "/path/to/pkcs12file.p12";

    /**
     * PKCS12 file passphrase.
     */
    final String KEY_STORE_PASSWORD = "correct horse battery staple";

    /**
     * URL to connect to. That is, a server for which the above certificate is required.
     */
    final String URL = "https://secure.example.org";

    @Test
    public void sslConnect() throws KeyStoreException, IOException, CertificateException,
            NoSuchAlgorithmException, KeyManagementException, UnrecoverableKeyException {

        // Load the key store, containing the client-side certificate.
        KeyStore keyStore = KeyStore.getInstance("pkcs12");
        InputStream keyStoreInput = new FileInputStream(KEY_STORE_PATH);
        keyStore.load(keyStoreInput, KEY_STORE_PASSWORD.toCharArray());
        System.out.println("Key store has " + keyStore.size() + " keys");

        // Create an SSL context with our private key store.
        // We are only loading the key-material here, but if your server uses a self-signed certificate,
        // you will need to load the trust-material (a JKS key-store containing the server's public SSL
        // certificate) as well.
        SSLContext sslContext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, KEY_STORE_PASSWORD.toCharArray())
                .useTLS()
                .build();

        // Prepare the HTTPClient.
        HttpClientBuilder builder = HttpClientBuilder.create();
        SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(
                sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        builder.setSSLSocketFactory(sslConnectionFactory);
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("https", sslConnectionFactory)
                .register("http", new PlainConnectionSocketFactory())
                .build();
        HttpClientConnectionManager ccm = new BasicHttpClientConnectionManager(registry);
        builder.setConnectionManager(ccm);

        // Perform a sample HTTP request.
        try (CloseableHttpClient httpClient = builder.build()) {
            HttpGet httpget = new HttpGet(URL);
            try (CloseableHttpResponse response = httpClient.execute(httpget)) {
                HttpEntity entity = response.getEntity();

                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                if (entity != null) {
                    System.out.println("Response content length: " + entity.getContentLength());
                    System.out.printf(EntityUtils.toString(entity));
                }
                EntityUtils.consume(entity);
            }
        }
    }
}

Thanks

1
  • What part of it fails? Commented Dec 19, 2018 at 3:07

1 Answer 1

1

The JRE 11 is not a problem but the TLSv1.3 it uses by default is. Apache HttpClient 5.0 has been tested for compatibility with JRE 11 TLSv1.3 but HttpClient 4.5 has not. For now just force the use of TLSv1.2 and the problem should go away.

Sign up to request clarification or add additional context in comments.

1 Comment

let me try this, I am using HttpClient 4.5, httpclient 5.0 still in beta

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.