Search code examples
androidsslhttpsself-signedandroid-ion

How to use self-signed SSL in android network library (ION)?


Using this network library:

https://github.com/koush/ion

As the current status is development, I would like to use self-signed SSL cert

The library forum has some discussion:

https://github.com/koush/ion/issues/3

 Ion ion = Ion.getDefault(c);
    ion.configure().createSSLContext("TLS");
    ion.getHttpClient().getSSLSocketMiddleware().setSSLContext(sslContext);
    ion.getHttpClient().getSSLSocketMiddleware().setTrustManagers(trustManagers);

After some studies , I have grab the crt and getting sslContext and trustmanager, the problem is , it still return exception

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

Here is my attempt :

    try {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = getResources().openRawResource(R.raw.load);
        Certificate ca;
        try {
            ca = cf.generateCertificate(caInput);
            //System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
        }

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

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

        ssl_context = SSLContext.getInstance("TLS");
        ssl_context.init(null, tmf.getTrustManagers(), null);
    } catch (Exception e) {
        Log.d("test1", "A: " + e);
    }

    Ion.getDefault(this).getHttpClient().getSSLSocketMiddleware().setTrustManagers(tmf.getTrustManagers());
    Ion.getDefault(this).getHttpClient().getSSLSocketMiddleware().setSSLContext(ssl_context);

    //test SSL
    Ion.getDefault(this).with(this)
            .load("https://na2b.no-ip.com/dragonair/can_app/api/media_list.php")
            .asJsonObject()
            .setCallback(new FutureCallback<JsonObject>() {
                @Override
                public void onCompleted(Exception e, JsonObject result) {
                    if (e != null) {
                        Log.d("test1", "B: " + e);
                    } else {
                        Log.d("test1", "result" + result);
                    }
                }
            });

notice that the exception is at the B: part so that means trustmanager and SSLcontext should build correctly, how to fix that?

Thanks for helping.


Solution

  • For your issue, IMO, you can refer to my following sample code. I have tested with my web service (Asp.Net WebAPI). Hope it helps!

    public class MainActivity extends AppCompatActivity {
    
        private Context mContext = this;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            try {
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                // cert file stored in \app\src\main\res\raw
                InputStream caInput = getResources().openRawResource(R.raw.your_cert);
    
                Certificate ca = cf.generateCertificate(caInput);
                caInput.close();
    
                KeyStore keyStore = KeyStore.getInstance("BKS");
                keyStore.load(null, null);
                keyStore.setCertificateEntry("ca", ca);
    
                String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
                tmf.init(keyStore);
    
                TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers());
    
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, wrappedTrustManagers, null);
    
                AsyncSSLSocketMiddleware sslMiddleWare = Ion.getDefault(mContext).getHttpClient().getSSLSocketMiddleware();
                sslMiddleWare.setTrustManagers(wrappedTrustManagers);
                sslMiddleWare.setHostnameVerifier(getHostnameVerifier());
                sslMiddleWare.setSSLContext(sslContext);
    
                // Post application/x-www-form-urlencoded and read a String
                Ion.with(mContext)
                        .load("https://yourserver/token")
                        .setBodyParameter("grant_type", "password")
                        .setBodyParameter("username", "bnk")
                        .setBodyParameter("password", "bnk123456789")
                        .asString()
                        .setCallback(new FutureCallback<String>() {
                            @Override
                            public void onCompleted(Exception e, String result) {
                                if (result != null) {
                                    Log.i("ionSample", result);
                                } else if (e != null) {
                                    e.printStackTrace();
                                }
                            }
                        });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private HostnameVerifier getHostnameVerifier() {
            return new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                    // or the following:
                    // HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
                    // return hv.verify("www.yourserver.com", session);
                }
            };
        }
    
        private TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers) {
            final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0];
            return new TrustManager[]{
                    new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            return originalTrustManager.getAcceptedIssuers();
                        }
    
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
                            try {
                                if (certs != null && certs.length > 0){
                                    certs[0].checkValidity();
                                } else {
                                    originalTrustManager.checkClientTrusted(certs, authType);
                                }
                            } catch (CertificateException e) {
                                Log.w("checkClientTrusted", e.toString());
                            }
                        }
    
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
                            try {
                                if (certs != null && certs.length > 0){
                                    certs[0].checkValidity();
                                } else {
                                    originalTrustManager.checkServerTrusted(certs, authType);
                                }
                            } catch (CertificateException e) {
                                Log.w("checkServerTrusted", e.toString());
                            }
                        }
                    }
            };
        }   
    }
    

    Logcat output:

    I/ionSample: {"access_token":"oS1SHxck8TzidTL...P-_6VFjRlDsjF9_A0JONu59rzYOVQV...ka78pHSvRPB5YrrBlHsF562Ay__Jd0MDfpOB0SRML2N8O3XPZK8woV4vjASzfGEzi7KJMmY8pkM_-P9ohHhWPD3PtgRahiqTUSapdpg6n197uJxdQWyU","token_type":"bearer","expires_in":2591999,"userName":"bnk",".issued":"Wed, 06 Jan 2016 06:26:45 GMT",".expires":"Fri, 05 Feb 2016 06:26:45 GMT"}