0

I'm currently developing an Android app (Android Studio 2.0), that will connect to my server (Glassfish 4.1, Netbeans 8.1) through HTTPS (using javax.net.ssl.HttpsURLConnection). This is currently all being run on my local network (smartphone + laptop). The problem I'm getting now is:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

I think because my Android application doesn't trust the server yet. How do I go about so it does indeed trust the server?

In some official documentation (http://developer.android.com/training/articles/security-ssl.html) and other guides, I've seen getting Keystores mentioned, or using .crt files. But where do I get either of those and how do I get them on my mobile device?

Currently my code looks like:

public static HttpsURLConnection setupHttpsConnection(URL url, Context context) {
    try {
        // Load CAs from an InputStream
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = new BufferedInputStream(context.getAssets().open("localhost.crt"));
        Certificate ca;
        try {
            ca = cf.generateCertificate(caInput);
            Log.d(LOG_TAG, "> setupHttpsConnection > ca.getSubjectDN = " + ((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
        }

        // Create a KeyStore containing our trusted CAs
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Create an SSLContext that uses our TrustManager
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);
        /*
        HostnameVerifier hostnameVerifier = new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                HostnameVerifier hv =
                        HttpsURLConnection.getDefaultHostnameVerifier();
                return hv.verify("192.168.0.121", session);
            }
        };
        */

        // Tell the URLConnection to use a SocketFactory from our SSLContext
        HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
        //urlConnection.setHostnameVerifier(hostnameVerifier);
        urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
        return urlConnection;

    } catch (Exception e) {
        e.printStackTrace();
        Log.d(LOG_TAG, e.toString());
        return null;
    }
}

Then in another place I call:

urlConnection = Utility.setupHttpsConnection(url, context);
urlConnection.connect(); // <-- Exception thrown here!
CounterFlame
  • 1,612
  • 21
  • 31
  • 1
    Have you checked [this](http://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https) question? – Madhukar Hebbar Mar 28 '16 at 10:44
  • This already helped, now the problem is the certificate I have has CN = localhost, but this localhost isn't know on my mobile phone, resulting in an "java.io.IOException: Hostname '192.168.0.121' was not verified. How can I change the CN to an IP address? – CounterFlame Mar 28 '16 at 12:50
  • How are you creating the certificate? X509Certificate? – Madhukar Hebbar Mar 28 '16 at 12:59
  • I now used "openssl req -x509 -sha256 -nodes -newkey rsa:2048 -days 365 -keyout localhost.key -out localhost.crt". This asks to fill in a few values, where for the CN I filled in 192.168.0.121 (IP address of the server). Using this .crt file now again results in "javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found." Is it a problem my HTTPS uses port 8181, and not the standard (which is 443 I think?) – CounterFlame Mar 28 '16 at 14:20
  • It's not like that. You can use any port. But some of the WIFI systems will block that.I read the article [here](http://developer.android.com/training/articles/security-ssl.html#HttpsExample) and implemented it. Wish it can solve your problem too. – Madhukar Hebbar Mar 28 '16 at 18:00
  • I implemented it from the article as well, how did you get/create your certificate tho? – CounterFlame Mar 28 '16 at 19:05

0 Answers0