I am developing an application on Android that uses REST web service. The web service is in HTTPS. I can't provide the web service details, as it is confidential. I followed the steps mentioned in the link below:
http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/
The application was working fine so far and was able to download the web service content. Suddenly last one week it failed to connect and throws "javax.net.ssl.SSLException: Not trusted server certificate". I followed the steps mentioned below to setup this:
Step 1: I used root certificate provided by GeoTrust in my application to enable secure communication. So collected root certificate "GeoTrust_Global_CA.cer" from Geo trust site: http://www.geotrust.com/resources/root-certificates/index.html
It is a Base64 encoded X.509 format.
Step 2: Downloaded BouncyCastle provider and by using this created key store. I ran following commands using java 6 keytool from command line to generate key store:
keytool -importcert -v -trustcacerts -file "G:\workspace\TestHttps\GeoTrustglobal.cer" -alias IntermediateCA -keystore "G:\workspace\TestHttps\res\raw\mykeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "G:\workspace\TestHttps\SigningProcess\bcprov-jdk16-146.jar" -storetype BKS -storepass mysecret
After it is successful, it creates myKeyStore.bks and I copied it to /res/raw folder of my application.
Then verified this key store by running the following command:
keytool -importcert -v -trustcacerts -file "G:\workspace\TestHttps\GeoTrustglobal.cer" -alias IntermediateCA -keystore "G:\workspace\TestHttps\res\raw\mykeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "G:\workspace\TestHttps\SigningProcess\bcprov-jdk16-146.jar" -storetype BKS -storepass mysecret
It returned 1 result with intermediate certificate as follows:
IntermediateCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 98:0F:C3:F8:39:F7:D8:05:07:02:0D:E3:14:5B:29:43
Step 3:
Now I wrote the following code that is extended from DefaultHttpClient
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(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.mykeystore);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
trusted.load(in, "mysecret".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);
}
}
}
Then I called DefaultHttpClient using following code:
package com.test.https;
import java.io.IOException;
import java.net.UnknownHostException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.os.Bundle;
public class TestHttps extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
startConnect();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void startConnect() throws UnknownHostException{
DefaultHttpClient client = new MyHttpClient(getApplicationContext());
HttpGet get = new HttpGet("https://ssltest15.bbtest.net/");
// Execute the GET call and obtain the response
HttpResponse getResponse = null;
try {
getResponse = client.execute(get);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch(UnknownHostException uhe){
uhe.printStackTrace();
throw new UnknownHostException();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String response = null;
if(getResponse != null){
HttpEntity responseEntity = getResponse.getEntity();
try {
response = EntityUtils.toString(responseEntity);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
When I executed this code, it throws following exception:
java.security.cert.CertPathValidatorException: TrustAnchor for CertPath not found.
javax.net.ssl.SSLException: Not trusted server certificate
So I tried the same application to connect to various other web services including one that is provided by geotrust (https://ssltest15.bbtest.net/) . All throw same exception. My guess on this issue is that,
Web server that is providing the REST web service, might had some changes on their side, that is causing this issue
The Geo Trust cerificate that I use is expired
Steps I followed have some issues
The same application with the above code was working fine before 1 week, suddenly failing now means, there is some change happened in the server side cause this issue. I am unclear about the exact issue.
If anybody can help me understand the issue is greatly appreciated. Thanks in advance.