3

我有一个 Android 应用程序,我在其中使用 HttpURLConnection 与我的服务器进行 SSL 连接。服务器证书包含具有有效 URI 的 CRL 分发点。此证书已被吊销,并且 URI 的 CRL 包含此信息。但是在握手期间我没有收到任何异常,我可以从我的服务器接收任何信息。我使用安卓 6 和 7。

我发现一些帖子,其中开发人员写道 Android 默认禁用撤销检查。另外,我看到了一些将 PREFER_CRLS 选项设置为 PKIXRevocationChecker 并将其设置为 TrustManagerFactory 的示例,但似乎它仅适用于 Java SE,当我在我的应用程序中尝试此代码时,我收到初始化 TrustManagerFactory 的异常:

java.security.InvalidAlgorithmParameterException: Unsupported spec: javax.net.ssl.CertPathTrustManagerParameters@dccac9. Only android.security.net.config.RootTrustManagerFactorySpi$ApplicationConfigParameters supported
    at android.security.net.config.RootTrustManagerFactorySpi.engineInit(RootTrustManagerFactorySpi.java:44)

network_security_config.xml 文件是正确的:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
     <base-config>
         <trust-anchors>
             <certificates src="@raw/ca_test"/>
         </trust-anchors>
     </base-config>
</network-security-config>

这是我的代码:

CertificateFactory cf = CertificateFactory.getInstance("X.509");
AssetManager am = getResources().getAssets();
Certificate ca;
try (InputStream caInput = am.open("ca_test.pem")) {
    ca = cf.generateCertificate(caInput);
    Log.d(LOG_TAG, "ca = " + ((X509Certificate) ca).getSubjectDN());
}

// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

KeyManagerFactory kmf =  
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
PKIXRevocationChecker rc =(PKIXRevocationChecker)cpb.getRevocationChecker();
rc.setOptions(EnumSet.of(
    PKIXRevocationChecker.Option.PREFER_CRLS, // prefer CLR over OCSP
    PKIXRevocationChecker.Option.SOFT_FAIL)); // handshake should not fail when CRL is not available
PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(keyStore, new X509CertSelector());
pkixParams.addCertPathChecker(rc);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(new CertPathTrustManagerParameters(pkixParams));
kmf.init(keyStore, null);

因此,我尝试了解如何为我的应用启用 CRL 检查。可以通过shell为根设备完成吗?有什么方法可以覆盖您自己的密钥库的参数吗?或者有什么方法可以为系统android密钥库启用它?

另外,我在这里发现了这个错误:https ://issuetracker.google.com/issues/36993981 ,但我没有看到这个问题的任何更新。有人知道适用于 Android 应用程序开发人员的任何解决方案吗?

4

0 回答 0