我的Android应用使用TLS与远程服务器通信。出于某种原因,当我在Genymotion虚拟机中运行我的应用程序时,TLS握手成功但在我在物理电话设备中运行时失败。
使用Wireshark查看流量我看到以下交换(服务器消息缩进):
TLSv1 Client Hello
TLSv1 Server Hello
TLSv1 Certificate
TLSv1 Certificate
TLSv1 Client Key Exchange
sslv3 Client Hello
sslv3 SSLv3 Record Layer: Alert (Level: Fatal, Description: Handshake Failure) (40)
根据我的阅读错误40,这可能是因为在一个共同的密码套件上缺乏一致意见:
http://support.citrix.com/article/CTX124731
经过调查,服务器似乎只支持单个密码套件:
密码套件:TLS_RSA_WITH_AES_128_CBC_SHA(0x002f)
SSLv3似乎不支持TLS_RSA_WITH_AES_128_CBC_SHA。
看起来奇怪的是,为什么握手会在第二个客户端Hello使用SSLV3协议时重新开始?
在涉及Genymotion虚拟设备的成功案例中,消息交换如下:
TLSv1 Client Hello
TLSv1 Server Hello
TLSv1 Certificate
TLSv1 Certificate, Client Key Exchange, Certificate Verify, Change Cipher Spec, Encrypted Handshake Message
TLSv1 [TCP Retransmission] Certificate
TLSv1 [TCP Retransmission] Client Key Exchange
TLSv1 New Session Ticket, Change Cipher Spec, Encrypted Handshake Message
**** *****更新
我使用以下代码片段更改了应用代码以强制进行TLSv1握手而不会回退到SSLv3:
SocketFactory sf = SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) sf.createSocket(host, 443);
socket.setEnabledProtocols(new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"});
socket.startHandshake();
这显示了wireshark中的以下内容:
TLSv1 Client Hello
TLSv1 Server Hello
TLSv1 Certificate
TLSv1 Certificate, Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
TLSv1 Alert (Level: Fatal, Description: Handshake Failure)
警报消息详细信息如下所示:
+Secure Sockets Layer
+TLSv1 Record Layer: Alert (Level: Fatal, Description: Handshake Failure)
+Content Type: Alert (21)
...
+Alert Message
Level: Fatal(2)
Description: Handshake Failure (40)
由于隐私限制,我无法附加wireshark pcap文件。谢谢你的帮助。