Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / security / cryptography

SSL Verification for Android Applications

4.25/5 (6 votes)
25 Apr 2011CPOL3 min read 95.6K   5  
Perform SSL Verification while using Web Services

Introduction

When we try to access a Web Service hosted on HTTPS and is secured over SSL, Host Verification and/or Peer Verification are to be handled in our application.

Background

Android supports the java.net and org.apache packages to access Web Services. I use Apache packages as I find them more useful and easier than using Java packages.

System Requirements

To Start

Host and Peer Verification are shown here. Each Android application has its own trusted store called KeyStore. In the KeyStore, we can store our self-signed SSL certificates that will be used for the verification purposes of our Web Service. Android trusts a couple of Trust Certificates, but if our signed certificate is not signed among those, then we need to add our certificate to the trusted store of the application.

Assuming you already have a self-signed certificate (if not, kindly use the key tool of Java to create one), let's add the certificate to a keystore using Bouncy Castle that we can access in our application. Like keytool is used in Java to create certificates, Bouncy Castle is the only way to add certificates to the Android keystore.

1. Creating the KeyStore

Download and unzip Bouncy Castle in a proper location and add the .jar file to the class path. Open cmd, go to the application folder, and type the following command:

keytool -import -v -trustcacerts -alias 0 -file mycertificate.crt 
  -keystore res/raw/mystore.bks -storetype BKS -provider 
  org.bouncycastle.jce.provider.BouncyCastleProvider -storepass mypassword
  • file parameter points to your certificate file that you want to add
  • keystore => gives the store name that you want to give
  • storepass => password to access the keystore

On successful execution of the command, the mystore.bks file will be generated successfully.

2. Create a Class to Use Our Store for HTTPS Connections

To use the store that we created above, we have to create a custom Apache DefaultHttpClient that knows to use the store for HTTPS requests.

Java
public class MyHttpClient extends DefaultHttpClient {

    final Context context;
    public MyHttpClient(Context context) {
        this.context = context;
    }

    @Override
    protected ClientConnectionManager createClientConnectionManager {
        SchemeRegistry registry = new SchemeRegistry();
        registry.register("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register("https", newSslSocketFactory(), 443));
        return new SingleClientConnManager(getParams(), registry);
    }

    private SSLSocketFactory newSslSocketFactory() {
        try {
             KeyStore trusted = KeyStore.getInstance("BKS");
             InputStream in = context.getResources().openRawResource(R.raw.mystore);
             try {
                 trusted.load(in, "mypassword".toCharArray());
             }
             finally {
                  in.close();
             }

             SSLSocketFactory mySslFact = new SslFactory(trusted);
             //mySslFact.setHostNameVerifier(new MyHstNameVerifier());
             return mySslFact;
         } catch(Exception e) {
         throw new AssertionError(e);
        }
    }
}

This code helps us to accept a server certificate and sets the certificate for verification. You can see how we are using our -storename parameter "BKS" to get the instance of the KeyStore, loading the certificate file mystore from R.raw, and setting its password that was used while adding it to the store.

3. Copy mystore File

Import the generated mystore.bks file to the res/raw folder. So our above class can access it from there.

With this, SSL Peer Verification is taken care of. We just have to create an instance of MyHttpClient in place of DefaultHttpClient and Peer Verification will be handled by itself.

4. Process for Host Verification

Android supports only the host/domain via which the web service is being called - if any other host is tried to connect it throws exception. For example, if our application connects to a host, and then tries to connect another host for any reason, Android won't allow to do that. For this to be allowed, we got to set the hostnames that we want to allow the application to access.

Java
public class MyHostVerifier extends org.apache.http.conn.ssl.AbstractVerifier {

    String[] allowHost = {"my.ultra.com", "your.ultra.com", "ours.ultra.com"}; 

    @Override

    public void verify(String host, String[] cns, 
	String[] subjectAlts) throws SSLException {
        // If the host is any the hosts to be allowed, return, else throw exception 
        for (int i=0; i < allowHost.length; i++) {
             if (host == allowHost[i])
                return;
        }
         throw SSLException;
    }
}

Uncomment setHostVerifier in the MyHttpClient class and our class is ready to handle SSL Host Verification as well.

That's it. Thanks.

History

  • 2011.04.25: Initial submission

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)