Java 通过另一个SSLSocket的SSLSocket
我正在尝试在Android应用程序中的另一个Java 通过另一个SSLSocket的SSLSocket,java,android,ssl,cryptography,sslsocketfactory,Java,Android,Ssl,Cryptography,Sslsocketfactory,我正在尝试在Android应用程序中的另一个SSLSocket上创建一个SSLSocket。较低的连接是到的SSL安全连接(HTTP proxy over SSL),较高的连接是HTTP over SSL(HTTPS) 为此,我使用了SSLSocketFactory的createSocket()函数,该函数允许传递一个现有套接字,通过该套接字运行SSL连接,如下所示: private Socket doSSLHandshake(Socket socket, String host, int po
SSLSocket
上创建一个SSLSocket
。较低的连接是到的SSL安全连接(HTTP proxy over SSL),较高的连接是HTTP over SSL(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
我正在安卓7.1.1上测试。该应用程序的目标是SDK级别23
- 我可能做错了什么李>
- 如何进一步调试该问题
- 有人有一个SSLSocket超过另一个SSLSocket的工作示例吗 最新Android版本上的SSLSocket
更新:同样的代码在Mac上的JRE 1.8中工作,但在Android上不工作
更新2:从概念上讲,以下是连接所经历的步骤:
更新3:我现在打开了一个GitHub回购协议,其中包含一个示例项目和tcpdumps:
注意:我已经找到并阅读了,但不幸的是,它没有包含太多有用的帮助。我不认为你做错了什么。在第二次握手时,协议协商中似乎存在错误。一个好的候选者可能会在NPN TLS握手扩展中失败 看看这个调用中的协议:
sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols());
您可以浏览列出的协议并单独尝试。看看是否可以锁定失败的部分,以及是否需要支持特定的协议或扩展 所以我试图找出安卓系统出现了什么问题,但到目前为止,我没有发现你的代码有任何问题。此外,由于该代码适用于JRE,因此它支持这一假设 从您提供的tcpdump中,有大量信息可以总结Android如何使用与JRE相同的API集 让我们看看JRE tcpdump:
- 请参阅初始握手消息(客户端Hello、服务器Hello、更改密码规范)。这显示了JRE客户端和代理服务器之间的握手。这是成功的李>
- 现在我们看不到JRE客户端和www.google.com(终端服务器)之间的第二次握手,因为这是加密的,因为我们正在通过SSL进行SSL。代理服务器正在将它们逐位复制到终端服务器。所以这是正确的行为
- 请参阅初始握手消息(客户端Hello、服务器Hello、更改密码规范)。这显示了android客户端和代理服务器之间的握手。这是成功的李>
- 现在理想情况下,我们不应该看到第二次握手,因为它应该被加密。但在这里,我们可以看到android客户端正在发送一个“client hello”,并将其发送到“www.google.com”,即使数据包被发送到代理服务器。
- 上面的注定会失败,因为数据包应该通过SSL套接字而不是最初的普通套接字写入。我查看了您的代码,发现您正在通过SSLSocket而不是普通套接字进行第二次握手李>
factory.createsocket()
with SSL socket)实现的一个bug,我觉得使用同一组API可能没有一个神奇的解决方法。事实上,我在android bug列表中发现了这个问题。请参阅以下链接:
这个问题仍然没有解决,您可能可以与android开发团队跟进以解决同样的问题
可能的解决方案:
如果我们认为同一套API无法工作,那么您只有一个选择:
I/SurfaceTextureClient(20733): [0x52851b98] frames:2, duration:1.005000, fps:1.989805
I/System.out(20733): [socket][2] connection /192.168.1.100:10443;LocalPort=35380(0)
I/System.out(20733): [CDS]connect[/192.168.1.100:10443] tm:90
I/System.out(20733): [socket][/192.168.1.123:35380] connected
I/System.out(20733): Doing SSL handshake with 192.168.1.100:10443
I/System.out(20733): Supported protocols are: [SSLv3, TLSv1, TLSv1.1, TLSv1.2]
E/NativeCrypto(20733): ssl=0x53c96268 cert_verify_callback x509_store_ctx=0x542e0a80 arg=0x0
E/NativeCrypto(20733): ssl=0x53c96268 cert_verify_callback calling verifyCertificateChain authMethod=RSA
I/System.out(20733): Doing SSL handshake with 192.168.1.100:443
I/System.out(20733): Supported protocols are: [SSLv3, TLSv1, TLSv1.1, TLSv1.2]
E/NativeCrypto(20733): Unknown error during handshake
I/System.out(20733): Shutdown rx/tx
I/System.out(20733): [CDS]close[35380]
I/System.out(20733): close [socket][/0.0.0.0:35380]
W/System.err(20733): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException:
SSL handshake aborted: ssl=0x53c9c1d8:
Failure in SSL library, usually a protocol error
W/System.err(20733): error:140770FC:SSL routines:
SSL23_GET_SERVER_HELLO:
unknown protocol (external/openssl/ssl/s23_clnt.c:766 0x4e7cb3ad:0x00000000)
W/System.err(20733): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:413)
W/System.err(20733): at com.bugreport.sslviassl.SecureWebProxyThread.doSSLHandshake(SecureWebProxyThread.java:147)
W/System.err(20733): at com.bugreport.sslviassl.SecureWebProxyThread.run(SecureWebProxyThread.java:216)
W/System.err(20733): Caused by: javax.net.ssl.SSLProtocolException:
SSL handshake aborted: ssl=0x53c9c1d8:
Failure in SSL library, usually a protocol error
W/System.err(20733): error:140770FC:SSL routines:
SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:766 0x4e7cb3ad:0x00000000)
W/System.err(20733): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
W/System.err(20733): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:372)
W/System.err(20733): ... 2 more
I/SurfaceTextureClient(20733): [0x52851b98] frames:5, duration:1.010000, fps:4.946089
public void policy()
{
int SDK_INT = android.os.Build.VERSION.SDK_INT;
if (SDK_INT > 8)
{
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
}