简体   繁体   English

Android webview ssl 相互认证握手问题

[英]Android webview ssl mutual auth handshake issue

I am trying to test ssl mutual certification of android webview.我正在尝试测试android webview的ssl相互认证。 I setup an environment as below and tested via PC web browser, everything is OK.我设置了如下环境并通过PC Web浏览器进行了测试,一切正常。 But I met the signature related issue during android webview test.但是我在 android webview 测试期间遇到了与签名相关的问题。 Can anybody help analyze which part of my test could be the cause?有人可以帮助分析我的测试的哪一部分可能是原因吗?

The test environment:测试环境:

  1. Android SDK 5.1 (since client certificate event callback API is opened since 5.0) Android SDK 5.1(因为客户端证书事件回调 API 从 5.0 开始开放)
  2. tomcat 8.0 https server, the type of server keystore is jks. tomcat 8.0 https服务器,服务器keystore类型为jks。
  3. client keystore type is PKCS12, Both client private key and ca trust certificate(self-signed) are save in it.客户端密钥库类型为 PKCS12,客户端私钥和 CA 信任证书(自签名)都保存在其中。

I customize WebviewClient which code is shown below.我自定义了 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();    
        }

    }

The handshake procedure I captured by ssldump is as follows.我用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

I notice that there are twice of ClientHello exists.我注意到有两次 ClientHello 存在。 From the tomcat log, I find the first round of handshake is ended at从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

The second round handshake is ended at第二轮握手结束于

*** 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

The detailed log of tomcat is posted on the link below. tomcat的详细日志贴在下面的链接上。 https://raw.githubusercontent.com/watanuoli/ssllog/master/README.md https://raw.githubusercontent.com/watanuoli/ssllog/master/README.md

Well its about 5 years old but I had the same issue.好吧,它大约 5 岁了,但我遇到了同样的问题。

This line is important:这一行很重要:

%% Invalidated:  [Session-29, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA]

Whereat TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA is a ciphre !而 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 是一个密码

This line means that the cipher has been invalidated by an server internal decision!此行表示密码已被服务器内部决定无效!

So the request is incomming from the browser to the server, the certificates are shared and the server decide - no matter if the certificate is valid, no matter if the chain-of-trust is valid no matter if access is granted or not, to reject the connection because the cipher has been invalidated by the server's internal configuration.所以请求从浏览器传入服务器,证书被共享,服务器决定 - 无论证书是否有效,无论信任链是否有效,无论是否授予访问权限,拒绝连接,因为密码已被服务器的内部配置无效。

In order to allow this chiphre to be valid for data-transfer, add this chiphre to the allowed ciphers in the server's configuration.为了允许此芯片对数据传输有效,请将此芯片添加到服务器配置中允许的密码中。

For Apache Tomcat you have to edit the server.xml .对于 Apache Tomcat,您必须编辑server.xml The xml-node Server->Service->Connector(usually port 443)->SSLHostConfig has a xml-attribute called ciphers , add your invalidated cipher to this xml-attribute (,-seperated). xml-node Server->Service->Connector(usually port 443)->SSLHostConfig有一个 xml-attribute 称为ciphers ,将您的无效密码添加到这个 xml-attribute (,-seperated)。

I guess you have to restart the server then.我想你必须重新启动服务器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM