在Android 5.0 Lollipop中,HttpClient失败并且Handshake Failed

Dmi*_*hin 15 ssl android handshake apache-httpclient-4.x android-5.0-lollipop

Android 5.0 Lollipop中的DefaultHttpClient似乎被打破了.它无法设置与先前版本的Android成功设置的某些网站的连接.

例如,我尝试连接到https://uralsg.megafon.ru

//Create httpclient like in https://stackoverflow.com/questions/18523784/ssl-tls-protocols-and-cipher-suites-with-the-androidhttpclient
HttpClient client = new DefaultHttpClient(manager, params);
HttpGet httpGet = new HttpGet("https://uralsg.megafon.ru");
HttpResponse client = httpclient.execute(httpGet);
Run Code Online (Sandbox Code Playgroud)

此代码适用于Android 2.3-4.4,但在Android 5.0(设备和模拟器)上失败,错误连接被对等关闭.当然这是可以理解的,因为Android 5.0尝试将这个旧服务器与TLSv1.2和现代密码连接起来,并且它不支持它们.

好的,使用SSL/TLS协议中的示例代码和带有AndroidHttpClient的密码套件,我们将协议和密码限制为TLSv1SSL_RSA_WITH_RC4_128_MD5.现在它失败了,出现了不同的错误:

javax.net.ssl.SSLHandshakeException: Handshake failed
caused by 
    error:140943FC:SSL routines:SSL3_READ_BYTES:sslv3 alert bad record mac 
    (external/openssl/ssl/s3_pkt.c:1286 0x7f74c1ef16e0:0x00000003) 
    at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake
Run Code Online (Sandbox Code Playgroud)

当然,这段代码在Android 2.3-4.4上运行顺畅.

我用wireshark检查了流量:

302 4002.147873000  192.168.156.30  83.149.32.13    TLSv1   138 Client Hello
303 4002.185362000  83.149.32.13    192.168.156.30  TLSv1   133 Server Hello
304 4002.186700000  83.149.32.13    192.168.156.30  TLSv1   1244    Certificate
305 4002.186701000  83.149.32.13    192.168.156.30  TLSv1   63  Server Hello Done
307 4002.188117000  192.168.156.30  83.149.32.13    TLSv1   364 Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
308 4002.240695000  83.149.32.13    192.168.156.30  TLSv1   61  Alert (Level: Fatal, Description: Bad Record MAC)
Run Code Online (Sandbox Code Playgroud)

您可以看到已建立连接但服务器已警告,因为它可能无法解码加密的握手消息.

我没有设法使用Android 5.0上的HttpClient 连接到https://uralsg.megafon.ru.股票浏览器确实连接它.Android 2.3-4.4以任何方式连接此站点没有任何困难.

有没有办法让HttpClient连接这些网站?这只是一个例子,我确信有很多旧版服务器无法通过Android 5.0和HttpClient连接.

ste*_*efs 5

更新:它原来是后端的一个bug,而不是android 5,虽然确实有问题的密码.

我有同样的问题.对我来说,它原来TLS_DHE_RSA_WITH_AES_256_GCM_SHA384是从android 5(更新的)默认密码集中选择的密码.

一旦我从可接受的密码的客户端列表中删除它,连接再次起作用.

机器人5更改日志中提到:

  • AES-GCM(AEAD)密码套件现已启用,

我很确定这是罪魁祸首.一旦TLS_DHE_RSA_WITH_AES_256_GCM_SHA384首选(由服务器),连接将失败.

请注意,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256有效.

我的猜测是Android的实现TLS_DHE_RSA_WITH_AES_256_GCM_SHA384是错误的,或者是你正在与之交谈的服务器之一.

解决方案:

  1. TLS_DHE_RSA_WITH_AES_256_GCM_SHA384从服务器上的可用密码中删除(无需重新部署应用程序).
  2. TLS_DHE_RSA_WITH_AES_256_GCM_SHA384从客户端提供的密码列表中删除(在此期间CLIENT_HELLO).

您可以通过实现自己的SSLSocketFactory并调用来在客户端执行此操作

sslSocket.setEnabledCipherSuites(String[] suites);
Run Code Online (Sandbox Code Playgroud)

在SSLSocket创建.

编辑:请注意,这不一定是一个android bug,可能是服务器实现有问题.如果你的问题确实是由密码引起的,请在android bug跟踪器上发表评论](https://code.google.com/p/android/issues/detail?id=81603).谢谢!