0

I'm trying to send HTTP request to application server, secured with SSL. I have a self-signed X.509 certificate from server team. I followed tutorial from documentation, but still got SSLHandshakeException : java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

I'm using this code:

CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");

AssetManager assManager = ShoppingHelperApp.getContext().getAssets();
InputStream is = assManager.open("keystore2.crt");
InputStream caInput = new BufferedInputStream(is);
Certificate ca = cf.generateCertificate(caInput);
caInput.close();

String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

context = SSLContext.getInstance("TLS");
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(context.getSocketFactory());

Does anyone has a clue how to solve it?

mol
  • 2,348
  • 4
  • 18
  • 34

1 Answers1

0

This is how I did similar thing to set up OkHttpClient:

OkHttpClient client = new OkHttpClient();
        try {
            KeyStore keyStore = SSLUtils.getKeyStore(applicationContext);
            SSLContext sslContext = SSLContext.getInstance("SSL");
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            sslContext.init(null,trustManagerFactory.getTrustManagers(), new SecureRandom());
            client.setSslSocketFactory(sslContext.getSocketFactory());
        } catch (Exception e) {
            Log.d("AppName", "cannot create http client", e);
        }

SSLUtils class:

import android.content.Context;
import android.content.res.AssetManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

public class SSLUtils {

    private static final Logger LOG = LoggerFactory.getLogger(SSLUtils.class.getSimpleName());

    public static KeyStore getKeyStore(Context context) {
        KeyStore keyStore = null;
        try {
            AssetManager assetManager = context.getAssets();
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            InputStream caInput = assetManager.open("cert.pem");
            Certificate ca;
            try {
                ca = cf.generateCertificate(caInput);
                LOG.debug("ca={}", ((X509Certificate) ca).getSubjectDN());
            } finally {
                caInput.close();
            }

            String keyStoreType = KeyStore.getDefaultType();
            keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", ca);
        } catch (Exception e) {
            LOG.error("Error during getting keystore", e);
        }
        return keyStore;
    }
}

Put your cert.pem file in assets directory.
I use slf4android for logging, but you can use standard Log class of course.

Hope it will help you :)

klimat
  • 23,063
  • 7
  • 56
  • 67
  • Thanks for the response! It seems to me, that our snippets are pretty much the same, except the certificate's extension. I tried with .pem, but it didn't worked either :( – mol Jun 08 '15 at 08:26
  • @mol itsn't a big deal ;) http://stackoverflow.com/questions/4691699/how-to-convert-crt-to-pem – klimat Jun 08 '15 at 08:28