I have a very specific SSL issue on my Android. If I try to visit a particular website via code, I get the following error:
SSL handshake failure: Failure in SSL library, usually a protocol error
error:140773F2:SSL routines:SSL23_GET_SERVER_HELLO: sslv3 alert unexpected message (external/openssl/ssl/s23_cInt.c:500 0xaf076228:0x00000000)
I get this regardless of the build... I've tried it on API levels 1.5, 1.6, 2.2, and 4.0 and gotten the same result each time.
After some troubleshooting I tried to visit the website through a browser and I got the following error:
Data connectivity problem
A secure connection could not be established.
Here's the thing, though... the website opens just fine on Windows browsers (tested on Firefox, IE, and Chrome). It also opens just fine on iOS devices which uses the same webkit as the Android, which is odd. The website also works without problems on the Opera Mini browser.
Here's the website.
I've tried workarounds by adding the client certificate to the keystore and by ignoring invalid client certificates, with no results. However it appears that the certificate itself is not the issue.
I'm at an impasse. Can anybody provide any guidance on how I can get this to work?
The most likely reason for the error is that the certificate authority that issued your SSL certificate is trusted on your desktop, but not on your mobile.
The date and time of the computer trying to access the website is incorrect. Having an untrusted SSL certificate. The website might contain insecure information. The SSL certificate might have wrong information.
I found the solution (thank you Nikolay for pointing me in the right direction).
The problem was two-fold... one, it was returning a site certificate that Android didn't like, and two, it had only SSLv3 (and not TLS) enabled.
Here was my solution. First I had to create a custom socket factory class:
public class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("SSLv3");
public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
SSLSocket S = (SSLSocket) sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
S.setEnabledProtocols(new String[] {"SSLv3"});
return S;
}
@Override
public Socket createSocket() throws IOException {
SSLSocket S = (SSLSocket) sslContext.getSocketFactory().createSocket();
S.setEnabledProtocols(new String[] {"SSLv3"});
return S;
}
}
Second, I had this custom HttpClient defined in my code:
public HttpClient getNewHttpClient() {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
MySSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
return new DefaultHttpClient();
}
}
Third, I called the custom HttpClient and parsed the results:
public String test(String URIString) {
HttpClient httpClient = getNewHttpClient();
String result = "";
URI uri;
try {
uri = new URI(URIString);
} catch (URISyntaxException e1) {
return "ERROR";
}
HttpHost host = new HttpHost(uri.getHost(), 443, uri.getScheme());
HttpPost httppost = new HttpPost(uri.getPath());
try {
HttpResponse response = httpClient.execute(host, httppost);
BufferedReader reader = new BufferedReader(
new InputStreamReader(
response.getEntity().getContent()
)
);
String line = null;
while ((line = reader.readLine()) != null){
result += line + "\n";
}
return result;
} catch (ClientProtocolException e) {
return "ERROR";
} catch (IOException e) {
return "ERROR";
}
}
How are you accessing this site? Through the Android browser? WebView? Or HttpClient/HTTPSURLConnection? It seems it only responds to SSL3, you have to force your client to use it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With