サーバーへの SSL 接続に HttpURLConnection を使用する Android アプリケーションがあります。サーバー証明書には、有効な URI を持つ CRL 配布ポイントが含まれています。この証明書は失効しており、URI による CRL にこの情報が含まれています。しかし、ハンドシェイク中に例外を受け取ることはなく、サーバーから情報を受け取ることができます。Android6と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 チェックを有効にする方法を理解しようとしています。ルートデバイスのシェル経由で実行できますか? 独自のキー ストアのパラメーターをオーバーライドする方法はありますか? または、システムのAndroidキーストアで有効にする方法はありますか?
また、ここでバグを見つけました: https://issuetracker.google.com/issues/36993981 しかし、この問題の更新はありません。Android アプリ開発者向けのソリューションを知っている人はいますか?