我知道有很多关于在Android中固定证书的问题,但我无法找到我想要的内容......
我将SSLSocketFactory
子类化并覆盖checkServerTrusted()
方法。在此方法中,我执行以下操作:
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate ca = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(PUB_KEY.getBytes("UTF-8")));
for (X509Certificate cert : chain) {
// Verifing by public key
cert.verify(ca.getPublicKey());
}
链中的一个项目验证而另一个不起作用(抛出Exception
)。我想我无法掌握证书链的工作原理。
相同的公共证书是否应该验证链中的所有证书?
答案 0 :(得分:1)
我发现在Android上实施证书固定的最简单方法是使用OkHttp库。
这是excerpt from the documentation:
默认情况下,OkHttp信任主机平台的证书颁发机构。此策略可最大限度地提高连接性,但受2011 DigiNotar attack等证书颁发机构攻击。它还假定您的HTTPS服务器的证书由证书颁发机构签名。
使用CertificatePinner来约束受信任的证书颁发机构。证书锁定可提高安全性,但会限制服务器团队更新其TLS证书的能力。 如果没有服务器的TLS管理员的祝福,请不要使用证书固定!
public CertificatePinning() {
client = new OkHttpClient();
client.setCertificatePinner(
new CertificatePinner.Builder()
.add("publicobject.com", "sha1/DmxUShsZuNiqPQsX2Oi9uv2sCnw=")
.add("publicobject.com", "sha1/SXxoaOSEzPC6BgGmxAt/EAcsajw=")
.add("publicobject.com", "sha1/blhOM3W9V/bVQhsWAcLYwPU6n24=")
.add("publicobject.com", "sha1/T5x9IXmcrQ7YuQxXnxoCmeeQ84c=")
.build());
}
public void run() throws Exception {
Request request = new Request.Builder()
.url("https://publicobject.com/robots.txt")
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
for (Certificate certificate : response.handshake().peerCertificates()) {
System.out.println(CertificatePinner.pin(certificate));
}
}
如果您需要支持自签名证书,Does OkHttp support accepting self-signed SSL certs?的答案将为您提供指导。
答案 1 :(得分:0)
相同的公共证书是否应与所有证书一起验证 链
答案: - 否。
大多数公共CA不直接签署服务器证书。相反,他们使用他们的主要CA证书(称为root CA
)来签署中间CA.他们这样做是为了使根CA可以离线存储以降低危害的风险。但是,像Android这样的操作系统通常直接trust only root CAs
,这使得中间CA签署的服务器证书与证书根证书之间存在短暂的信任差距。
要解决此问题,服务器不会仅发送客户端 SSL握手期间的证书,但来自的证书链 服务器CA通过任何必要的中间人来达到可信任的 根CA.
检查this link以获取更多信息。希望这会对用户有所帮助。
答案 2 :(得分:0)
a中的证书和公钥固定(也称为证书固定) 简而言之-
通常,应用程序信任所有预安装的CA。如果这些CA中的任何一个要颁发欺诈性证书,则该应用程序将受到中间人攻击(也就是窃听)的威胁。某些应用选择通过限制其信任的CA集合或通过证书固定来限制其接受的证书集合。证书固定是通过按公钥哈希提供一组证书来完成的。证书固定是一种依靠客户端上的服务器证书验证的方法。
以下是在Android上实现证书固定的3种方法-
老式方法-TrustManager-https://medium.com/@ric…/ssl-pinning-on-android-8baa822e3bd5
OkHttp CertificatePinner-https://square.github.io/…/okh…/okhttp3/-certificate-pinner/
新鲜事物-网络安全配置-https://developer.android.com/trai…/articles/security-config
特别是对于您的问题,您可以使用<pin-set>
标签通过NSC中公钥的哈希配置证书。
请注意,在使用证书固定时,应始终包括一个备份密钥,这样,如果您被迫切换到新密钥或更改CA(在固定为CA证书或该CA的中间证书时),您的应用程序的连接不受影响。否则,您必须向应用程序推送更新以恢复连接。
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">example.com</domain>
<pin-set expiration="2018-01-01">
<pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
<!-- backup pin -->
<pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin>
</pin-set>
</domain-config>
</network-security-config>