SSL握手在Android仿真器中中止

时间:2018-08-07 10:18:21

标签: java android ssl

我将Nexus 5X(API级别27)用作React Native应用的仿真器。我正在尝试使用SSLSockets将其连接到我的Java服务器,但是在连接它后立即出现错误:握手失败

SSL handshake aborted: ssl=0x9613a1c0: Failure in SSL library, usually a protocol error
error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE (external/boringssl/src/ssl/tls_record.cc:579 0x9679afc0:0x00000001)
error:1000009a:SSL routines:OPENSSL_internal:HANDSHAKE_FAILURE_ON_CLIENT_HELLO (external/boringssl/src/ssl/handshake_client.cc:893 0xa43b3dc3:0x00000000)
invoke        JavaMethodWrapper.java:383
invoke        JavaModuleWrapper.java:160
run        NativeRunnable.java
handleCallback        Handler.java:790
dispatchMessage        Handler.java:99
dispatchMessage        MessageQueueThreadHandler.java:29
loop        Looper.java:164
run        MessageQueueThreadImpl.java:192
run        Thread.java:764*

有一段时间,由于错误消息,我认为它正在使用SSLv3,但是在Wireshark中检查了连接之后,我注意到它实际上是TLSv1.2。然后,我尝试为服务器和android客户端强制实施特定的密码套件,而没有运气。编写自定义SocketFactory类也无济于事。

我发现了另一个可能与我的问题有关的问题:SSLHandshakeException: Handshake failed on Android N/7.0。我仍然相当有信心,我的问题与受支持的密码套件和/或椭圆曲线密码学有关。

Android客户端代码

SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket connection = (SSLSocket) factory.createSocket("127.0.0.1", 4192);

connection.setEnabledProtocols(new String[]{"TLSv1.1", "TLSv1.2"});
connection.setUseClientMode(true);

DataOutputStream output = new DataOutputStream(connection.getOutputStream());
DataInputStream input = new DataInputStream(connection.getInputStream());

String[] cipher_suites = connection.getSupportedCipherSuites();
connection.setEnabledCipherSuites(cipher_suites);

connection.startHandshake();

服务器代码

SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket server = (SSLServerSocket) factory.createServerSocket(4192, 1);

SSLSocket connection = (SSLSocket) server.accept();

DataInputStream input = new DataInputStream(connection.getInputStream());
DataOutputStream output = new DataOutputStream(connection.getOutputStream());

connection.setEnabledProtocols(new String[]{"TLSv1.1", "TLSv1.2"});

String[] cipher_suites = connection.getSupportedCipherSuites();
connection.setEnabledCipherSuites(cipher_suites);

connection.startHandshake();

服务器本身可以正常工作,并且可以使用完全相同的代码从另一台计算机连接。它在openjdk 10.0.1上运行。与android相同的版本。有趣的是,它在发行说明中说:

security-libs / javax.net.ssl  3DES密码套房残疾人 为了提高SSL / TLS连接的强度,已通过jdk.tls.disabledAlgorithms安全属性在JDK的SSL / TLS连接中禁用了3DES密码套件。

模拟器中的android版本是8.1,我也在物理设备上用7.0测试了它。错误消息都是一样的。有人遇到过这个问题吗?

捕获的密码套件

这些是我随客户端Hello收到的密码套件和已确认的TLS版本

Version: TLS 1.2 (0x0303)
Cipher Suites (14 suites)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
    Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
    Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
    Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
    Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)

接着是握手失败警报:

TLSv1.2 Record Layer: Alert (Level: Fatal, Description: Handshake Failure)
    Content Type: Alert (21)
    Version: TLS 1.2 (0x0303)
    Length: 2
    Alert Message
        Level: Fatal (2)
        Description: Handshake Failure (40)

1 个答案:

答案 0 :(得分:1)

我终于开始工作了。问题是我用错误的算法创建了密钥库文件。我使用keytool通过-keyalg RSA创建了一个新商店,现在我的服务器可以在客户端上使用通用RSA密码了。