【发布时间】:2017-06-24 00:11:30
【问题描述】:
我正在尝试在 Android 应用中在另一个 SSLSocket 之上创建一个 SSLSocket。下层连接是到Secure Web Proxy(基于 SSL 的 HTTP 代理)的 SSL 安全连接,上层连接是基于 SSL 的 HTTP (HTTPS)。
为此,我正在使用 SSLSocketFactory 的 createSocket() 函数,该函数允许传递一个现有的 Socket 来运行 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。
- 我可能做错了什么?
- 如何进一步调试问题?
- 有没有人有一个 SSLSocket 超越另一个的工作示例 最新 Android 版本上的 SSLSocket?
非常感谢任何帮助!
更新:完全相同的代码在 Mac 上的 JRE 1.8 中有效,但在 Android 上无效。
更新 2:从概念上讲,这些是连接所经历的步骤:
- 从 Android 应用程序连接到安全代理服务器(套接字)
- 与代理服务器进行 SSL/TLS 握手(SSLSocket over Socket)
- 通过 SSLSocket 向代理服务器发送 CONNECT 消息
- 代理连接到目标 (https) 服务器,从现在开始只复制字节
- 与目标 (https) 服务器进行 SSL/TLS 握手(SSLSocket over SSLSocket over Socket)
- 将 GET 消息发送到目标服务器并读取响应
问题出现在第 5 步,在 SSLSocket 上进行握手时 通过 SSLSocket(通过 Socket)。
更新 3:我现在打开了一个包含示例项目和 tcpdump 的 GitHub 存储库:https://github.com/FD-/SSLviaSSL
注意:我已经找到并阅读了a question with very similar title,但遗憾的是它并没有包含太多有用的帮助。
【问题讨论】:
-
你误会了。您不需要外部插座。代理将向目标使用 SSL。
-
您使用的是什么代理,需要客户端和代理之间的通信才能通过 SSL 确保安全?这是非常不寻常的。通常,客户端会使用不安全的连接与代理进行通信,并且只有在代理连接到目标服务器后,客户端才会启动与目标的 SSL 握手。代理只是一种静默传递,唯一的加密是在客户端和目标之间,而不是在客户端和代理之间。
-
@RemyLebeau 这可能不寻常,但我的设置需要通过 SSL 连接与代理通信。
-
您可能知道如何按照链接问题的解决方案中的建议使用不同的 SSL 提供程序吗?
-
@EJP 当我说我确实需要这个时请相信我。抽象出确切的用例:为什么 SSL 上的 SSL 不起作用?
标签: java android ssl cryptography sslsocketfactory