okhttp 无法正确验证引脚

okhttp doesn't validate pins correctly

AVD with Android 6.0 上使用 com.squareup.retrofit2:retrofit:2.0.1com.squareup.okhttp3:okhttp:3.2.0。 我正在尝试使用由根 CA 签名的自签名证书来实现 public 密钥固定。该根 CA 位于系统 CA 信任库中。

使用 okhttp wiki 提供的示例并进行一些小改动:

OkHttpClient client = new OkHttpClient.Builder().certificatePinner(
                new CertificatePinner.Builder()
                        .add(pinningUrl, "sha256/invalidPIN")
                        .build()).build();
Request request = new Request.Builder()
                .url(pinningUrl)
                .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));
}

发生的情况是 response.isSuccessful returns 正确,没有抛出异常,尽管 pin 不正确。唯一正确完成的是使用系统 CA 信任库中的根 CA 验证证书。

我发现有效的方法是在 for 循环之前添加这一行。但这不是正确的方法,因为请求已经发送,固定应该在 TLS 协商完成之前起作用。此外,我发现的任何示例代码中都没有提到这一行。

client.certificatePinner().check(pinningUrl, response.handshake().peerCertificates());

投掷

javax.net.ssl.SSLPeerUnverifiedException: Certificate pinning failure!

是okhttp提供的示例代码有bug还是我哪里做错了?

您配置不正确。将 pinningUrl 替换为固定的主机名 URL。例如,您需要 example.com 而不是 http://example.com/。如果你想发送一个 PR 来使主机名验证更严格,那将是非常欢迎的。