0

I am trying to make a SSL connection from my app to an internal server. I download a PKCS12 file that contains all needed certs and CA. I then load it to a keystore which I use to make my SSL call.

When I make my SSL call, I get the following Exception: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Looking at the android dev website, it looks like this is due to an unknown certificate authority.

Here is my code so far:

private void testConnect(String base64Pkcs) {
    KeyStore keyStore;
    SSLContext sslContext = null;
    TrustManager trustManager = null;
    try {
        keyStore = KeyStore.getInstance("PKCS12");
        writeFile(base64Pkcs);
        if (keyStore != null) {
            keyStore.load(readFile(), DEBUG_CERT_PWD.toCharArray());

            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(keyStore, DEBUG_CERT_PWD.toCharArray());
            KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();

            sslContext = SSLContext.getInstance("TLS");
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
            trustManagerFactory.init(keyStore);
            sslContext.init(keyManagers, trustManagerFactory.getTrustManagers(), null);
            trustManager = trustManagerFactory.getTrustManagers()[0];

            OkHttpClient client = new OkHttpClient.Builder()
                    .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManager)
                    .build();

            final Request request = new Request.Builder().url(getApplication().getString(R.string.https_test_endpoint_url)).build();

            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    Log.e(TAG, "Error while calling the test secure endpoint", e);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    Log.d(TAG, response.message());
                    if (response.body() != null) {
                        Log.d(TAG, response.body().string());
                    }
                }
            });
        }
    } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException | KeyManagementException e) {
        //TODO: Handle exceptions
        Log.wtf(TAG, e);
    }
}

I am able to get the connection working by manually extracting the CA from the PKCS12 file using openSSL, put it in my app assets, and load it using:

openssl pkcs12 -in tls.pkcs -cacerts -nokeys -chain -out tls.trust - password pass:mydevpassword`
keyStore.setCertificateEntry("ca", myCaCert);` 

My problem is that I can't use openSSL from my app to export the CA and load it to the keystore programmatically. Are there any way to do that or am I stuck having to include the CA in the app assets?

jww
  • 97,681
  • 90
  • 411
  • 885
Distwo
  • 11,569
  • 8
  • 42
  • 65
  • 1
    It doesn't make sense to use the same file as both keystore and truststore. `KeyManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())` should be `KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())` of course. – user207421 Feb 15 '18 at 22:17
  • Good catch! I fixed that... – Distwo Feb 15 '18 at 23:11

1 Answers1

0

Is the problem that you have not set networkSecurityConfig in the manifest?

https://stackoverflow.com/a/60102517/114265

Brian S
  • 3,096
  • 37
  • 55