一篇文章让您了解HTTPS( 三 )

有时候CA也是不可信的,为了获得更高的安全新,需要我们自己指定新人的锚点,可以采用如下的代码:
// 取到证书的输入流InputStream is = new FileInputStream("anchor.crt");CertificateFactory cf = CertificateFactory.getInstance("X.509");Certificate ca = cf.generateCertificate(is);// 创建 Keystore 包含我们的证书String keyStoreType = KeyStore.getDefaultType();KeyStore keyStore = KeyStore.getInstance(keyStoreType);keyStore.load(null);keyStore.setCertificateEntry("anchor", ca);// 创建一个 TrustManager 仅把 Keystore 中的证书 作为信任的锚点String algorithm = TrustManagerFactory.getDefaultAlgorithm();TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(algorithm);trustManagerFactory.init(keyStore);TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();// 用 TrustManager 初始化一个 SSLContextSSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(null, trustManagers, null);return sslContext.getSocketFactory();这种情况下,只有 anchor.crt 以及他签发的证书才会被信任 。

  • SecureRandom,也就是生成随机数的策略,一般都是直接new SecureRandom()作为参数传进去 。
注意这里使用的是单向认证,也就是只需要客户端验证服务端的证书,客户端本地部缓存证书,所以这里sslContext.init()方法的三个参数都是空的 。
默认的 SSLSocketFactory 校验服务器的证书时(也就是TrustManager[]传空的时候),会信任设备内置的100多个根证书 。
既然有单向验证,那么也有双向验证,即不仅仅客户端需要校验服务端,服务端也需要验证客户端 。这种情况下,客户端需要将自己的证书发给服务端做验证,这种情况只需要将证书的KeyManager作为在init()的第一个参数来SSLContext就行了 。




推荐阅读