使用X509TrustManagerExtensions checkServerTrusted进行公钥绑定



为HTTPS TLS连接绑定公钥

Android API有一个问题,低于17,在公钥固定的情况下启用MITM(中间人)攻击。这已经在下面的链接中解释了。

https://www.cigital.com/blog/ineffective-certificate-pinning-implementations/

所以在Android最小sdk低于17,即,低于Android版本4.2,我们需要初始化X509TrustManager与Android密钥库只有服务器根证书(而不是默认的密钥库;这将在设备中安装所有证书)。这有助于在执行公钥绑定之前清理从服务器接收到的叶子证书。

从Android API 17开始,Android引入了X509TrustManagerExtensions,它在操作系统级别执行这种根清理。

https://developer.android.com/reference/android/net/http/X509TrustManagerExtensions.html

我的问题:

如果有人能提供一个关于如何实现X509TrustManagerExtensions提供的用于根清理的以下方法的示例,我将很高兴。

List<X509Certificate> checkServerTrusted (X509Certificate[] chain, 
                String authType, 
                String host)

我被下面的内容弄糊涂了。

  1. host;应该是域名URL吗?是否使用HTTPS ?或者应该是完整的url(域名+相对路径)

  2. 如何创建一个X509TrustManagerExtensions的瞬间?X509TrustManagerExtensions的构造函数将X509TrustManager作为输入。我们是否使用android默认密钥存储库创建这个X509TrustManager ?

代码片段(不工作):

   TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
   tmf.init(KeyStore.getInstance(KeyStore.getDefaultType()));
   for (TrustManager trustManager : tmf.getTrustManagers()) {
       X509TrustManagerExtensions tme = new X509TrustManagerExtensions((X509TrustManager) trustManager);
       tme.checkServerTrusted(chain, authType, <<String https://www.example.com>>);
   }

例外:没有找到证书路径的信任锚

可能存在的安全风险:使用KeyStore.getDefaultType()

首先,您需要通过使用TrustManagerFactory来获得信任管理器。当初始化它时,您将null传递给它以使用默认的Keystore,它将返回默认的信任管理器。这样,您就可以使用第一个X509TrustManager创建X509TrustManagerExtensions

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
        TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
// Find first X509TrustManager in the TrustManagerFactory
X509TrustManager x509TrustManager = null;
for (TrustManager trustManager : trustManagerFactory.getTrustManagers()) {
    if (trustManager instanceof X509TrustManager) {
        x509TrustManager = (X509TrustManager) trustManager;
        break;
    }
}
X509TrustManagerExtensions x509TrustManagerExtensions = 
        new X509TrustManagerExtensions(trustManager());

然后执行这个主机,我已经成功地使用了域名部分:

List<X509Certificate> trustedCerts = x509TrustManagerExtensions
        .checkServerTrusted(untrustedCerts, "RSA", "appmattus.com");

对于使用HttpUrlConnection的证书,不可信证书由以下命令确定:

Certificate[] serverCerts = ((HttpsUrlConnection)conn).getServerCertificates();
X509Certificate[] untrustedCerts = Arrays.copyOf(serverCerts, 
        serverCerts.length, 
        X509Certificate[].class);

如果你正在使用OkHttp,那么你可以使用内置的CertificatePinner,它已经更新,以修复在那篇文章中提到的问题。

相关内容

  • 没有找到相关文章

最新更新