Android SSL 证书固定

mtb*_*b81 5 ssl android

我知道有很多关于 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());                      
}
Run Code Online (Sandbox Code Playgroud)

链中的一项进行了验证,而另一项则没有进行验证(这会抛出Exception)。我想我无法理解证书链是如何工作的。

是否应该使用同一个公共证书来验证链中的所有证书?

0xc*_*ced 1

我发现在 Android 上实现证书固定的最简单方法是使用OkHttp库。

\n

以下是文档的摘录

\n
\n

默认情况下,OkHttp 信任主机平台的证书颁发机构。此策略最大限度地提高了连接性,但它容易受到证书颁发机构攻击,例如2011 DigiNotar 攻击。它还假设您的 HTTPS 服务器\xe2\x80\x99 证书由证书颁发机构签名。

\n

使用CertificatePinner来限制哪些证书颁发机构是可信的。证书固定可提高安全性,但会限制您的服务器团队\xe2\x80\x99s 更新其 TLS 证书的能力。未经服务器\xe2\x80\x99s TLS 管理员的许可,请勿使用证书固定!

\n
\n
  public CertificatePinning() {\n    client = new OkHttpClient();\n    client.setCertificatePinner(\n        new CertificatePinner.Builder()\n            .add("publicobject.com", "sha1/DmxUShsZuNiqPQsX2Oi9uv2sCnw=")\n            .add("publicobject.com", "sha1/SXxoaOSEzPC6BgGmxAt/EAcsajw=")\n            .add("publicobject.com", "sha1/blhOM3W9V/bVQhsWAcLYwPU6n24=")\n            .add("publicobject.com", "sha1/T5x9IXmcrQ7YuQxXnxoCmeeQ84c=")\n            .build());\n  }\n\n  public void run() throws Exception {\n    Request request = new Request.Builder()\n        .url("https://publicobject.com/robots.txt")\n        .build();\n\n    Response response = client.newCall(request).execute();\n    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);\n\n    for (Certificate certificate : response.handshake().peerCertificates()) {\n      System.out.println(CertificatePinner.pin(certificate));\n    }\n  }\n
Run Code Online (Sandbox Code Playgroud)\n

如果您需要支持自签名证书,请回答OkHttp 支持接受自签名 SSL 证书吗?会指导你。

\n