I have an Android app which uses an SSLSocketFactory to load a pkcs12 certificate and use that certificate to perform SSL Client authentication with my server. This process worked perfectly on Android 2.1, 2.2, and 2.3, but when I attempt to run this code on a phone or emulator running 4.0 my server does not receive a public key from the request made by my application.
Here is the code I am using to get the HttpClient I use to perform my request
private HttpClient getHttpClient(Context context) {
if(httpClient == null) {
KeyStore mycert = KeyStore.getInstance("pkcs12");
byte[] pkcs12 = persistentStorage.getPKCS12Certificate(context);
ByteArrayInputStream pkcs12BAIS = new ByteArrayInputStream(pkcs12);
mycert.load(pkcs12BAIS, config.getPassword().toCharArray());
SSLSocketFactory sockfact = new SSLSocketFactory(mycert, null, null);
sockfact.setHostnameVerifier(new StrictHostnameVerifier());
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("https",sockfact , config.getPort()));
BasicHttpParams httpParameters = new BasicHttpParams();
HttpProtocolParams.setUseExpectContinue(httpParameters, false);
HttpProtocolParams.setVersion(httpParameters, HttpVersion.HTTP_1_1);
HttpConnectionParams.setConnectionTimeout(httpParameters, 3000);
HttpConnectionParams.setSoTimeout(httpParameters, 3000);
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(httpParameters, registry);
cm.closeExpiredConnections();
cm.closeIdleConnections(3000, TimeUnit.MILLISECONDS);
httpClient = new DefaultHttpClient(cm, httpParameters);
}
return httpClient;
}
So it turns out that as of ICS the SSLSocketFactory (or some other part of the system) will no longer properly accept unsigned x509 certificates (which I used to create the pkcs12 cert). I just had to self sign the certificate and my existing java code worked fine.