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,个人心得)