8

My Android application should be able to communicate to any SSL enabled servers. As my app is demo application and my customers add their own SSL server details in the app while logging in, so upfront I don't know which SSL certificate I need to validate.

Following is my earlier code.

public SSLSocketFactory getSSLSocketFactory(String hostname) {
        try {
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
            SSLContext context = SSLContext.getInstance("TLS");
            context.init(null, new X509TrustManager[] { new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            } }, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  HttpsURLConnection.getDefaultSSLSocketFactory();
    }

When I updated my to playstore, it was rejected with below reason

To properly handle SSL certificate validation, change your code in the checkServerTrusted method of your custom X509TrustManager interface to raise either CertificateException or IllegalArgumentException whenever the certificate presented by the server does not meet your expectations. For technical questions, you can post to Stack Overflow and use the tags “android-security” and “TrustManager."

I would like to update my code similar to this

public static HttpClient wrapClient(HttpClient base) {
try {
    SSLContext ctx = SSLContext.getInstance("TLS");
    X509TrustManager tm = new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

        public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };
    ctx.init(null, new TrustManager[]{tm}, null);
    SSLSocketFactory ssf = new SSLSocketFactory(ctx);
    ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    ClientConnectionManager ccm = base.getConnectionManager();
    SchemeRegistry sr = ccm.getSchemeRegistry();
    sr.register(new Scheme("https", ssf, 443));
    return new DefaultHttpClient(ccm, base.getParams());
} catch (Exception ex) {
    return null;
}

}

Does playstore accept this? is there any better way to handle this?

Thanks in Advance.

3 Answers 3

10

quoting the solution from: https://gist.github.com/aembleton/889392

The following code disables SSL certificate checking for any new instances of HttpsUrlConnection:

 /**
 * Disables the SSL certificate checking for new instances of {@link HttpsURLConnection} This has been created to
 * aid testing on a local box, not for use on production.
 */
public static void disableSSLCertificateChecking() {
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
            // Not implemented
        }

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
            // Not implemented
        }
    } };

    try {
        SSLContext sc = SSLContext.getInstance("TLS");

        sc.init(null, trustAllCerts, new java.security.SecureRandom());

        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } });
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

from where I need to call this method?
it doesn't really matter - anywhere in your code - just call it once per application lifetime
2

In case someone is looking to disable SSL certificate checking in a NativeScript Android app, here's how to convert Elad's answer's code to JavaScript:

  const disableSSLCertificateCheckin = function () {
    const trustAllCerts = [new javax.net.ssl.X509TrustManager({
      getAcceptedIssuers: function () {
        return null
      },

      checkClientTrusted: function (arg0, arg1) {
        // Not implemented
      },

      checkServerTrusted: function (arg0, arg1) {
        // Not implemented
      },
    })]

    try {
      const sc = javax.net.ssl.SSLContext.getInstance('TLS')
      sc.init(null, trustAllCerts, new java.security.SecureRandom())

      javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory())
      javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
        new javax.net.ssl.HostnameVerifier({
          verify: function (hostname, session) {
            return true
          }
        })
      )
    } catch (e) {
      console.log('e :>> ', e);
    }
  }

  disableSSLCertificateCheckin()

Thanks @Elad!

1 Comment

It works, but a small error in the text. Is javax.net.ssl.HttpsURLConnection.HttpsURLConnection should be javax.net.ssl.HttpsURLConnection.
1

This is an old post, but I hope it can help someone else. Problem is fixed with netcipher version 2.1.0 (SSLHandshakeException with v1.2.1)

File app/build.gradle

...
dependencies {
    implementation 'info.guardianproject.netcipher:netcipher:2.1.0'
...
}

1 Comment

It worked as a charm for an update to an old app!

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.