我正在尝试在安卓应用程序中创建一个基于另一个SSLSocket
的SSLSocket
。较低的连接是到安全 Web 代理(通过 SSL 的 HTTP 代理)的 SSL 安全连接,而较高的连接是用于 SSL 上的 HTTP(HTTPS)。
为此,我正在使用 SSLSocketFactory 的createSocket()
函数,该函数允许传递现有的套接字以运行 SSL 连接,如下所示:
private Socket doSSLHandshake(Socket socket, String host, int port) throws IOException {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager(){
public X509Certificate[] getAcceptedIssuers(){ return null; }
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}
};
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new SecureRandom());
SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket(socket, host, port, true);
sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols());
sslSocket.setEnableSessionCreation(true);
sslSocket.startHandshake();
return sslSocket;
} catch (KeyManagementException | NoSuchAlgorithmException e) {
throw new IOException("Could not do handshake: " + e);
}
}
当底层套接字为普通的TCP套接字时,此代码正常工作。但当我使用上述代码创建的SSLSocket作为底层套接字时,握手失败并出现以下异常:
javax.net.ssl.SSLHandshakeException: Handshake failed
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:429)
at com.myapp.MyThreadClass.doSSLHandshake(MyThreadClass.java:148)
at com.myapp.MyThreadClass.run(MyThreadClass.java:254)
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x7374d56e80: Failure in SSL library, usually a protocol error
error:100000e3:SSL routines:OPENSSL_internal:UNKNOWN_ALERT_TYPE (external/boringssl/src/ssl/s3_pkt.c:618 0x738418ce7e:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
... 2 more
我在Android 7.1.1上进行测试,应用程序的目标SDK级别为23。
- 我可能做错了什么?
- 我该如何进一步调试此问题?
- 有没有任何人有一个在最近的Android版本上使用另一个SSLSocket的工作示例?
非常感谢任何帮助!
更新:相同的代码在Mac上的JRE 1.8中可以运行,但在Android上不能。
更新2:从Android应用程序开始,与安全代理服务器(Socket)建立连接
- 与代理服务器(SSLSocket over Socket)进行SSL/TLS握手
- 通过SSLSocket向代理服务器发送CONNECT消息
- 代理连接到目标(https)服务器并仅复制字节
- 与目标(https)服务器(SSLSocket over SSLSocket over Socket)进行SSL/TLS握手
- 发送GET消息以获取响应
问题出现在第5步,当对一个在SSLSocket上的SSLSocket执行握手时。
更新3:我现在已经打开了一个GitHub repo,其中包含一个样本项目和tcpdumps:https://github.com/FD-/SSLviaSSL
注意:我已经发现并阅读了一个具有非常相似标题的问题,但不幸的是它没有包含太多有用的帮助。