HttpClient fails with Handshake Failed in Android 5.0 Lollipop HttpClient fails with Handshake Failed in Android 5.0 Lollipop android android

HttpClient fails with Handshake Failed in Android 5.0 Lollipop


update: it turned out to be a bug in the back-end, not android 5, though indeed with the cipher in question.

I had the same problem. For me it turned out to be the cipher TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 which was chosen from android 5's (updated) set of default ciphers.

As soon as i removed it from the client list of acceptable ciphers, connections worked again.

The android 5 change log mentions:

  • AES-GCM (AEAD) cipher suites are now enabled,

I'm pretty sure this is the culprit. As soon as TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 is preferred (by the server), the connection will fail.

Note that TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 works.

My guess is that either the Android implementation of TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 is buggy, or the one of the server you're talking to.

Solutions:

  1. Remove TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 from the available ciphers on the server (no app redeployment needed).
  2. Remove TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 from the list of ciphers the client offers (during the CLIENT_HELLO).

You can do that on the client side by implementing your own SSLSocketFactory and calling

sslSocket.setEnabledCipherSuites(String[] suites);

on SSLSocket creation.

edit: note that this isn't necessarily an android bug, it might be that the server implementation is faulty. if your problem is indeed caused by the cipher, please leave a comment on the android bug tracker](https://code.google.com/p/android/issues/detail?id=81603). thank you!


I tried changing the cipherSuites in a custom socket factory, but that did not help. In my case, I had to remove the TLSv1.1 and TLSv1.2 protocols from the socket's EnabledProtocols. It appears that some older servers do not handle the protocol negotiation for the new protocols very well. There are various examples out there for creating a custom socket factory, such as How to override the cipherlist sent to the server by Android when using HttpsURLConnection?, and other ones for Apache sockets. That being done, I just called the following AdjustSocket method to remove the protocols.

private void AdjustSocket(Socket socket){    String[] protocols = ((SSLSocket) socket).getSSLParameters().getProtocols();    ArrayList<String> protocolList = new ArrayList<String>(Arrays.asList(protocols));    for (int ii = protocolList.size() - 1; ii >= 0; --ii )        {        if ((protocolList.get(ii).contains("TLSv1.1")) || (protocolList.get(ii).contains("TLSv1.2")))            protocolList.remove(ii);        }    protocols = protocolList.toArray(new String[protocolList.size()]);    ((SSLSocket)socket).setEnabledProtocols(protocols);}