I am currently working on the migration of an Android from HttpClient to UrlConnection. I am facing some issue on, at least, Android 4.2.2.
The URL I am trying to call to is an https URL and I have to use a client certificate.
Based on this blog article, I wrote the following code :
// We create the client PKCS12 certificate
final KeyStore clientCertificateKeyStore = KeyStore.getInstance("PKCS12");
try
{
clientCertificateKeyStore.load(this.clientCertificatePayload, this.clientCertificatePassword.toCharArray());
}
finally
{
this.clientCertificatePayload.close();
}
final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
keyManagerFactory.init(clientCertificateKeyStore, clientCertificatePassword.toCharArray());
final KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, null, null);
And later in my code, I use the sslContext
variable to set the SSL Factory my httpURLConnection
:
((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(sslContext.getSocketFactory());
This code works perfectly on my Nexus 5 with Android 6.0.1 but does not work on a Wiko Rainbow with Android 4.2.2. In fact, after setting the sslSocketFactory to my httpURLConnection
, I have the following exception when I call the getOutputStream
method :
Caused by: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x631b60c8: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x59b4c8a8:0x00000000)
at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:421)
at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)
at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:486)
at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:450)
at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81)
at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:205)
at libcore.net.http.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:281)
at com.splunk.mint.network.http.MonitorableHttpsURLConnection.getOutputStream(MonitorableHttpsURLConnection.java:93)
at com.smartnsoft.droid4me.ws.URLConnectionWebServiceCaller.performHttpRequest(URLConnectionWebServiceCaller.java:472)
at com.smartnsoft.droid4me.ws.URLConnectionWebServiceCaller.performHttpRequest(URLConnectionWebServiceCaller.java:562)
at com.smartnsoft.droid4me.ws.URLConnectionWebServiceCaller.getInputStream(URLConnectionWebServiceCaller.java:158)
... 14 more
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x631b60c8: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x59b4c8a8:0x00000000)
at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHand
I tried several solutions including this one but I still have the exception.
Do you have any idea how to make the code working on Android 4.2.2 ?
Thank you for your help !
Edit : Here the way I use the NoSSLv3Factory
.
Basically, I use the same code to create the client PKCS12 certificate and initialize the the SSLContext
. The difference is when I set the SSLSocketFactory
to my HttpUrlConnection
. Here the condition I tried to use :
if (httpURLConnection instanceof HttpsURLConnection)
{
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP)
{
((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(sslContext.getSocketFactory());
}
else
{
((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new NoSSLv3Factory());
}
}
I also tried to use another version of the constructor using the code :
((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new NoSSLv3Factory(sslContext.getSocketFactory()));
But I still have the same exception :(