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.
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:
Collapse
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.
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.
Read more: Codeproject