Android webview ssl相互身份验证握手问题

时间:2015-11-14 17:02:43

标签: android tomcat ssl ca

我正在尝试测试android webview的ssl相互认证。 我设置了如下环境,并通过PC网络浏览器进行测试,一切正常。但我在android webview测试期间遇到了签名相关的问题。 任何人都可以帮助分析我的测试的哪个部分可能是原因吗?

测试环境:

  1. Android SDK 5.1(自5.0以来打开客户端证书事件回调API)
  2. tomcat 8.0 https服务器,服务器密钥库的类型是jks。
  3. 客户端密钥库类型为PKCS12,客户端私钥和ca信任证书(自签名)都保存在其中。
  4. 我自定义WebviewClient,代码如下所示。

        public class SSLWebViewClient extends WebViewClient {
            private X509Certificate[] certificatesChain;  
            private PrivateKey clientCertPrivateKey;
    
            private InputStream certfile_p12;
            private String certfile_password = "";
            private Context context;
    
            public SSLWebViewClient(Context context) throws Exception {
                super();
                this.context = context;
                initPrivateKeyAndX509Certificate();
            }  
    
            private void initPrivateKeyAndX509Certificate() throws Exception {  
                KeyStore keyStore;
    
                certfile_password = "123456";
                certfile_p12 = context.getResources().getAssets().open("client.p12");
                keyStore = KeyStore.getInstance("PKCS12");
                keyStore.load(certfile_p12, certfile_password.toCharArray());
                clientCertPrivateKey = (PrivateKey) keyStore.getKey("client", certfile_password.toCharArray());
                certificatesChain = new X509Certificate[1];
                certificatesChain[0] = (X509Certificate)keyStore.getCertificate("server");
            }
    
            @Override
            public void onReceivedClientCertRequest(WebView view, ClientCertRequest handler) {
                if((null != clientCertPrivateKey) && ((null!=certificatesChain) && (certificatesChain.length !=0))){  
                    handler.proceed(this.clientCertPrivateKey, this.certificatesChain);   
                }else{  
                    handler.cancel();  
                }         
            }
    
    
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
    
            @Override  
            public void onReceivedSslError(final WebView view, SslErrorHandler handler,  
                    SslError error) {         
                handler.proceed();    
            }
    
        }
    

    我通过ssldump捕获的握手程序如下。

    2 1  0.0094 (0.0094)  C>S  Handshake      ClientHello
    2 2  0.0369 (0.0274)  S>C  Handshake      ServerHello
        Certificate
        ServerKeyExchange
        CertificateRequest
    Not enough data. Found 266 bytes (expecting 32767)
        ServerHelloDone
    2    0.1244 (0.0874)  C>S  TCP FIN
    2    0.1247 (0.0003)  S>C  TCP FIN
    New TCP connection #3: 222.130.170.32(17617) <-> worknode(8443)
    3 1  0.0074 (0.0074)  C>S  Handshake      ClientHello
    3 2  0.0373 (0.0299)  S>C  Handshake      ServerHello
        Certificate
        ServerKeyExchange
        CertificateRequest
    Not enough data. Found 266 bytes (expecting 32767)
        ServerHelloDone
    3 3  0.1089 (0.0715)  C>S  Handshake      Certificate
    3 4  0.1089 (0.0000)  C>S  Handshake      ClientKeyExchange
    3 5  0.1089 (0.0000)  C>S  Handshake      CertificateVerify
    Not enough data. Found 258 bytes (expecting 16384)
    3 6  0.1089 (0.0000)  C>S  ChangeCipherSpec
    3 7  0.1089 (0.0000)  C>S  Handshake
    3 8  0.1514 (0.0424)  S>C  Alert          fatal          bad_certificate
    3    0.1514 (0.0000)  S>C  TCP FIN
    3    0.3448 (0.1933)  C>S  TCP FIN
    

    我注意到ClientHello存在两倍。 从tomcat日志中,我发现第一轮握手在

    结束
    *** ServerHelloDone
    http-nio-8443-exec-2, WRITE: TLSv1.2 Handshake, length = 1683
    http-nio-8443-exec-4, called closeOutbound()
    http-nio-8443-exec-4, closeOutboundInternal()
    http-nio-8443-exec-4, SEND TLSv1.2 ALERT:  warning, description = close_notify
    http-nio-8443-exec-4, WRITE: TLSv1.2 Alert, length = 2
    

    第二轮握手在

    结束
    *** CertificateVerify
    Signature Algorithm SHA512withRSA
    http-nio-8443-exec-6, fatal error: 42: certificate verify message signature error
    javax.net.ssl.SSLHandshakeException: certificate verify message signature error
    %% Invalidated:  [Session-29, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA]
    http-nio-8443-exec-6, SEND TLSv1.2 ALERT:  fatal, description = bad_certificate
    http-nio-8443-exec-6, WRITE: TLSv1.2 Alert, length = 2
    http-nio-8443-exec-6, fatal: engine already closed.  Rethrowing javax.net.ssl.SSLHandshakeException: certificate verify message signature error
    

    tomcat的详细日志发布在下面的链接中。 https://raw.githubusercontent.com/watanuoli/ssllog/master/README.md

1 个答案:

答案 0 :(得分:0)

它大约 5 岁了,但我遇到了同样的问题。

这一行很重要:

%% Invalidated:  [Session-29, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA]

而 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 是一个密码

这一行表示密码已被服务器内部决定无效!

因此请求从浏览器传入服务器,证书被共享,服务器决定 - 无论证书是否有效,无论信任链是否有效,无论是否授予访问权限或否,拒绝连接,因为密码已被服务器的内部配置无效。

为了允许此芯片对数据传输有效,请将此芯片添加到服务器配置中允许的密码中。

对于 Apache Tomcat,您必须编辑 server.xml。 xml-node Server->Service->Connector(usually port 443)->SSLHostConfig 有一个名为 ciphers 的 xml-attribute,将您的无效密码添加到这个 xml-attribute (,-seperated)。

我猜你必须重新启动服务器。