Java: HTTPS requests with certificates using HttpClient (two-way authentication)


You need to send GET requests to the server via HTTPS. For these purposes, use Apache HttpClient 3.1.0

The problem is that the server requires a certificate (two-way authentication). I was provided with two files: client.cert.pem and client.key.pem, from which I obtained keystore.jks and keystore.p12 using keytool and openssl.

I use curl I am successfully getting data from the server

curl --cert client.cert.pem --key client.key.pem ...

But in the code I can't pass the certificate correctly.

By studying many examples on the Internet I came up with this code:

final char[] JKS_PASSWORD = "password".toCharArray();

SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(
    new File("ssl/keystore.jks"), JKS_PASSWORD, new TrustSelfSignedStrategy()).build();

HttpClient httpsClient = HttpClients.custom().setSSLContext(sslContext).build();
HttpResponse rResponse = httpsClient.execute(new HttpGet(MY_URL));

In this case y I get an exception:

java.lang.NoSuchMethodError: org.apache.http.impl.client.HttpClientBuilder.setSSLContext(Ljavax/net/ssl/SSLContext;)Lorg/apache/http/impl/client/HttpClientBuilder;

If you use SSLConnectionSocketFactory:

...

SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
        sslContext,
        new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" },
        null,
        SSLConnectionSocketFactory.getDefaultHostnameVerifier());


HttpClient httpsClient = HttpClients.custom().setSSLSocketFactory(sslSocketFactory).build();
HttpResponse rResponse = httpsClient.execute(new HttpGet(MY_URL));

Discarded:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I obviously messed up something, but I can't figure out what. Any help is welcome!

Author: Aray Karjauv, 2017-07-20

2 answers

I have a mobile application for android that uses its CA to verify the certificate chain. Try taking a piece of code or an algorithm from here. It's certainly not for the Apache client. But, I think, something common can be distinguished. before sending the request, I call

....
SSLConnection.setSSLSocketFactory(MakeOWN_CASocketFactory());
....
 
SSLSocketFactory MakeOWN_CASocketFactory() {
        if (!useOwnCAForTLS || !serverURI.contains("DOMAIN.LOCAL")) return null;
        if (sslContext == null) {
            try {
                Debug("SocketFactoryOWN_CA(): Получаем локальное хранилище...");
                KeyStore localTrustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                InputStream rawRes = settingsContext.get().getResources().openRawResource(R.raw.OWN_CA_root_ca);
                Debug("SocketFactoryOWN_CA():Загружаем локальное хранилище корневых сертификатов");
                localTrustStore.load(rawRes, "PASSWORD_THERE".toCharArray());
                trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                trustManagerFactory.init(localTrustStore);
                sslContext = SSLContext.getInstance("TLS");
                Debug("SocketFactoryOWN_CA(): формируем SSL-контекст");
                sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());

                return sslContext.getSocketFactory();
            } catch (Exception e) {
                Debug("loadOWN_CATrustStore(): Ошибка: " + e.getMessage());
            }
            return null;
        } else {
            try {
                sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());

            } catch (Exception e) {
                Debug("loadOWN_CATrustStore(): Ошибка: " + e.getMessage());
            }
            return (localSocketFactory = sslContext.getSocketFactory());
        }
    }
 1
Author: Yakov, 2020-09-24 19:10:10

Try this way:

String keyPhrase = "your_key_there";

KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(getClass().getClassLoader().getResourceAsStream("your_cert"), keyPhrase
  .toCharArray());

SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keyStore, keyPhrase.toCharArray()).build();

HttpGet httpGet = new HttpGet("your_url_there");

HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
HttpResponse response = httpClient.execute(httpGet);
 0
Author: GVArt, 2017-07-21 06:48:32