Canalblog
Editer l'article Suivre ce blog Administration + Créer mon blog
Publicité
It was not (so) obvious
31 octobre 2014

Connecting with https to a url using a self signed certificate

Something good to know when for instance you have to connect to a QA backend that doesn't have a valid certificate. Here's how to proceed:

1st step: download bouncycastle

Android uses Bouncycastle to handle ssl certificates. It uses version 1.46 Keystores generated with later versions won't work for Android and will cause exceptions like java.io.IOException: Wrong version of key store on runtime 

Download Bouncycastle

2nd step: get the certificate of the site

There are different ways to achieve this. Using openssl in command line for instance or opening the url in a browser, checking the certificate details and saving the certificate to a file (*.cer)

3rd step: generate a keystore

This can be done using the keytool program found in your JDK. Use the following command:

keytool -import -v -trustcacerts -alias 0 -file [full certificate name] -keystore [keystore file name].bks -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerPath [path to Jar file]/bcprov-jdk15on-146.jar -storepass [password]

A bks file should be created after this step

4th step: copy the keystore to your Android project

The file should be copied to resources/raw

5th step: add the following class to your project

public class MyHttpsClient extends DefaultHttpClient {
    final Context context;
    
    public MyHttpsClient(Context context) {
        this.context = context;
    }
  
    @Override
    protected ClientConnectionManager createClientConnectionManager() {
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        // Register for port 443 our SSLSocketFactory with our keystore
        // to the ConnectionManager
        registry.register(new Scheme("https", newSslSocketFactory(), 443));
        return new SingleClientConnManager(getParams(), registry);
    }
  
    private SSLSocketFactory newSslSocketFactory() {
        try {
            // Get an instance of the Bouncy Castle KeyStore format
            KeyStore trusted = KeyStore.getInstance("BKS");
            // Get the raw resource, which contains the keystore with
            // your trusted certificates (root and any intermediate certs)
            InputStream in = context.getResources().openRawResource(R.raw.keystore);
            try {
                // Initialize the keystore with the provided trusted certificates
                // Also provide the password of the keystore
                trusted.load(in, "password".toCharArray());
            } finally {
                in.close();
            }
            // Pass the keystore to the SSLSocketFactory. The factory is responsible
            // for the verification of the server certificate.
            SSLSocketFactory sf = new SSLSocketFactory(trusted);
            // Hostname verification from certificate
            // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
            sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
            return sf;
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}

Remember to update the password and change the resource name if necessary.

6th step: Call your new Https client from your code

defaultHttpClient client = new MyHttpClient(getApplicationContext());

Post inspired by:
http://blog.antoine.li/2010/10/22/android-trusting-ssl-certificates/
http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html
http://stackoverflow.com/questions/11963852/wrong-version-of-key-store-error-how-can-i-create-a-version-1-keystore-certif


Publicité
Publicité
Commentaires
It was not (so) obvious
Publicité
Archives
Publicité