android|android https 双向认证--高级

https双向认证,这种一般不会在android遇到,因为这种正常是服务器和服务器之间通信采用,而且是银行金融类用的比较多。用在android端的话,不仅起不到安全作用,反而会让https不安全,因为加密对称秘钥的公私钥需要存放在客户端。具体为什么不安全,这是很基础的知识,这里不讲。
正常需要用到双向认证时,会给我们2个证书:Ca证书和.p12结尾的证书,这种做法比较简单,网上到处都有,不赘述。
这里我们要讨论的是,有的情况,给我们的证书是4个文件:

  1. ca证书(单向认证时使用),
  2. 公钥证书
  3. 私钥(这个是一对)
  4. 服务器认证客户端的证书


解决方法:
SSLContext sslContext = SSLContext.getInstance("TLS"); CertificateFactory cf = CertificateFactory.getInstance("X.509"); // 客户端认证服务端 InputStream in = BaseUtils.getApp().getAssets().open("puk.crt"); // 这个puk.crt文件可以是16进制的也可以是Base64后的 Certificate ca = cf.generateCertificate(in); KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); trustStore.setCertificateEntry("ca", ca); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(trustStore); // 服务端认证客户端 KeyStore keyStore = KeyStore.getInstance("PKCS12"); keyStore.load(null, null); Certificate secondPuk = cf.generateCertificate(new ByteArrayInputStream(Base64.decode(cert1))); Certificate secondCert = cf.generateCertificate(new ByteArrayInputStream(Base64.decode(cert2))); PrivateKey privateKey = Utils.getPrivatekey(pem); if(privateKey == null){ return null; } KeyStore.PrivateKeyEntry secondPri = new KeyStore.PrivateKeyEntry(privateKey, new Certificate[]{secondPuk}); // 加载证书 keyStore.setCertificateEntry("cert", secondCert); keyStore.setEntry("pri", secondPri, null); // 初始化KeyManagerFactory KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509"); //(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(keyStore, null); sslContext.init(null, trustManagerFactory.getTrustManagers(), null); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); OkHttpClient okHttpClient = new OkHttpClient.Builder()// 构建OKHttp客户端 .sslSocketFactory(socketFactory) .build();

【android|android https 双向认证--高级】

    推荐阅读