How to import self-signed SSL certificate to Volley on Android 4.1+
Asked Answered
O

4

15

I develop android application which uses Volley. All communication is done via HTTPS connection. Because I test it on local environment, I use self-signed certificates for Tomcat.

Before, I had only android 2.3 and 3.0 devices. Now I've got also 4.1 and 4.4.

My implementation uses this approach: http://developer.android.com/training/articles/security-ssl.html (part Unknown certificate authority) On devices with Android up to 4.1 it works perfectly. SSLSocketFactory with custom certificates is passed to Volley:

Volley.newRequestQueue(getApplicationContext(), new HurlStack(null, socketFactory));

But what happens on Android 4.1+? Why it does not work? I tried also with NullX509TrustManager like this:

private static class NullX509TrustManager implements X509TrustManager {
    @Override
    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType)
            throws CertificateException {
    }

    @Override
    public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType)
            throws CertificateException {
    }

    @Override
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

But it still does not work...

Otto answered 25/2, 2014 at 16:46 Comment(0)
O
4

I've resolved it with solution mentioned here:

http://developer.android.com/training/articles/security-ssl.html

Common Problems with Hostname Verification

by adding custom hostname verifier which returns true for my hostname in Volley project and editing HurlStack openConnection method:

if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {            
    ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);
    ((HttpsURLConnection)connection).setHostnameVerifier(new CustomHostnameVerifier());         
}
Otto answered 27/2, 2014 at 13:23 Comment(1)
i dont understandMarchellemarcher
W
5

Trust all SSL certificates:- You can bypass SSL if you want to test on the testing server. But do not use this code for production.

public static class NukeSSLCerts {
protected static final String TAG = "NukeSSLCerts";

public static void nuke() {
    try {
        TrustManager[] trustAllCerts = new TrustManager[] { 
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    X509Certificate[] myTrustedAnchors = new X509Certificate[0];  
                    return myTrustedAnchors;
                }

                @Override
                public void checkClientTrusted(X509Certificate[] certs, String authType) {}

                @Override
                public void checkServerTrusted(X509Certificate[] certs, String authType) {}
            }
        };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        });
    } catch (Exception e) { 
    }
}

}

Please call this function in onCreate() function in Activity or in your Application Class.

NukeSSLCerts.nuke();

This can be used for Volley in Android. More Ref. https://newfivefour.com/android-trust-all-ssl-certificates.html

Washstand answered 4/7, 2017 at 11:52 Comment(0)
O
4

I've resolved it with solution mentioned here:

http://developer.android.com/training/articles/security-ssl.html

Common Problems with Hostname Verification

by adding custom hostname verifier which returns true for my hostname in Volley project and editing HurlStack openConnection method:

if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {            
    ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);
    ((HttpsURLConnection)connection).setHostnameVerifier(new CustomHostnameVerifier());         
}
Otto answered 27/2, 2014 at 13:23 Comment(1)
i dont understandMarchellemarcher
A
2

If you already have a .crt file and looking to get it attached to Volley then here are 2 simple steps to follow.

Step 1: Write this method to your code.

public SSLSocketFactory getSocketFactory(Context context)
        throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {

    // Load CAs from an InputStream (could be from a resource or ByteArrayInputStream or ...)
    CertificateFactory cf = CertificateFactory.getInstance("X.509");

    InputStream caInput = new BufferedInputStream(context.getResources().openRawResource(R.raw.myFile));
                                                   // I paste my myFile.crt in raw folder under res.
    Certificate ca;

    //noinspection TryFinallyCanBeTryWithResources
    try {
        ca = cf.generateCertificate(caInput);
        System.out.println("ca=" + ((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);

    return sslContext.getSocketFactory();
}

Step 2: Just add this below line before you make any request using Volley.

HttpsURLConnection.setDefaultSSLSocketFactory(getSocketFactory(context));

Android Studio will ask you to enclose that line in try/catch for all Exceptions thrown by our method. So just let it do that.

Happy Coding!

Abohm answered 3/7, 2019 at 7:36 Comment(1)
How to verify that my certificate added successfully and it's working perfectly?Funeral
K
0

The easiest method I found is adding this class and executing it from onCreate method

new NukeSSLCerts().nuke();

It will make volley to Trust all SSL certificates

Kkt answered 26/4, 2016 at 19:8 Comment(4)
Exactly "It will make volley to Trust all SSL certificates", remember that It's not safe for production environment.Nigritude
@BhavinPatel usually we are using different environments for developing the application. We can have, development environment, staging, testing, UAT, SIT environments and so on. The environments are varying according to each project. But at the end of the development phase -including all phases of testing-, we should go live which means to real clients and uses and this is called Production Environment. Hope this helps. Thank you.Shaftesbury
@Shaftesbury ya get it.Magdalenemagdalenian
@Shaftesbury Always Welcome sir.Magdalenemagdalenian

© 2022 - 2024 — McMap. All rights reserved.