我正在尝试测试android webview的ssl相互认证。 我设置了如下环境,并通过PC网络浏览器进行测试,一切正常。但我在android webview测试期间遇到了签名相关的问题。 任何人都可以帮助分析我的测试的哪个部分可能是原因吗?
测试环境:
我自定义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
答案 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)。
我猜你必须重新启动服务器。