在 SO 上提出 SSL 固定问题似乎是在向空洞大喊大叫,但这里……
我需要在 Android 上实现 SSL 固定,并且我正在处理一些要求/约束:
- 它应该验证整个证书链,而不仅仅是叶子。
- 它需要与 Volley 库一起使用
根据 Google 的教程,我想出了以下用于创建 SSLSocketFactory 的实现:
CertificateFactory factory = CertificateFactory.getInstance("X.509");
final KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("leaf_cert", getCertificate(factory, R.raw.leaf_cert));
keyStore.setCertificateEntry("interm_cert1", getCertificate(factory, R.raw.interm_cert1));
keyStore.setCertificateEntry("interm_cert2", getCertificate(factory, R.raw.interm_cert2));
keyStore.setCertificateEntry("root_cert", getCertificate(factory, R.raw.root_cert));
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
return sslContext.getSocketFactory();
当我创建一个新HttpStack
实例时使用这个 SSLSocket 工厂。请注意,我按照它们在链中的位置顺序列出了证书。
为了验证此代码,我利用 Google 的nogotofail
Android 演示应用程序修改了NoSslCertificateChainOfTrustCheckTest
. 看起来固定工作正常,但我实际上只需要包含leaf_cert
在KeyStore
. 使用openssl
,我验证服务器只发回叶证书。在这一点上,事情变得非常奇怪:
- 我的团队构建的姊妹 iOS 应用程序使用 AFNetworking 来完成证书固定繁重的工作,它实际上强制所有四个证书都存在。换句话说,尽管只取回了叶子证书,但它正在验证整个链。
- 当我实际尝试在项目中使用代码时(再次使用 Volley),我发现我不仅不需要整个证书链,我只需要包含
leaf_cert
ORiterm_cert1
即可。
总而言之,我需要回答以下问题:
- 我的钉扎实现真的能完成它的工作吗?
- 验证整个链条需要什么魔法?
- 为什么我可以用中间证书代替叶子证书,为什么我只能使用 Volley 而不是 in
nogotofail
?