我已将CertStore设置为使用本地存储的CRL配置。我想仅使用这些本地存储的CRL进行证书验证。如果传入连接的证书与这些CRL中的任何一个不匹配,则不应尝试从CDP点获取CRL而只是尝试softfail。有没有办法实现这个目标?
System.setProperty("com.sun.security.enableCRLDP", "false");
KeyManagerFactory keyManagerFactory = null;
KeyStore keyStore = null;
keyManagerFactory = KeyManagerFactory.getInstance(keyAlgorithm);
keyStore = KeyStore.getInstance(keyStoreType);
ksFile = new FileInputStream(keyStoreFile);
keyStore.load(ksFile,password);
keyManagerFactory.init (keyStore,password);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", "SunJSSE");
CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
List<CertStore> certStores = new ArrayList<>();
Collection<CRL> crls = new HashSet<>();
crls.add(CertificateFactory.getInstance("X.509").generateCRL( new java.io.FileInputStream("crl path")));
crls.add(CertificateFactory.getInstance("X.509").generateCRL( new java.io.FileInputStream("crl path2")));
certStores.add(CertStore.getInstance("Collection", new CollectionCertStoreParameters(crls)));
PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker();
rc.setOptions(EnumSet.of(
PKIXRevocationChecker.Option.PREFER_CRLS, // prefer CLR over OCSP
// handshake should not fail when CRL is not available
PKIXRevocationChecker.Option.NO_FALLBACK));
CertPathParameters pkixParams = new PKIXBuilderParameters(keyStore, new X509CertSelector());
// PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(keyStore, new X509CertSelector());
((PKIXParameters) pkixParams).setRevocationEnabled(true);
((PKIXParameters) pkixParams).setCertStores(certStores);
((PKIXParameters) pkixParams).addCertPathChecker(rc);
tmf.init( new CertPathTrustManagerParameters(pkixParams) );
SSLContext context = SSLContext.getInstance(protocol);
context.init (keyManagerFactory.getKeyManagers (), tmf.getTrustManagers(), null);
答案 0 :(得分:1)
审核PKIXRevocationChecker文档和checkCRLs代码,我看到com.sun.security.enableCRLDP
除了在传统模式下没有被使用,如果提供的CRL不适合,则会下载 CRL验证证书
您可以查看/调试DistributionPointFetcher.verifyCRLs中正在应用的条件,了解CRL未被使用的原因
验证给定证书的分发点的CRL,以确保它适合检查撤销状态。
static boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point,X509CRL crl, boolean[] reasonsMask, boolean signFlag,PublicKey prevKey, X509Certificate prevCert, String provider,Set<TrustAnchor> trustAnchors, List<CertStore> certStores,Date validity) throws CRLException, IOException {
替代:自行检查撤销
您需要禁用默认吊销检查才能使用自己的CRL列表。我认为你可以包装默认的TrustManager
以包括服务器认证链的信任验证期间的撤销检查
首先删除((PKIXParameters) pkixParams).setRevocationEnabled(true);
,然后添加此代码
//tmf.init(...);
TrustManager[] trustManagers = tmf.getTrustManagers();
final X509TrustManager origTrustmanager = (X509TrustManager)trustManagers[0];
TrustManager[] wrappedTrustManagers = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return origTrustmanager.getAcceptedIssuers();
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
origTrustmanager.checkClientTrusted(certs, authType);
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
//Original trust checking
origTrustmanager.checkServerTrusted(certs, authType);
//Check revocation with each CRL
//from docs: CertificateException - if the certificate chain is not trusted by this TrustManager.
for (CRL crl: crls){
if (crl.isRevoked(certs[0]){
throw new CertificateException (e);
}
}
}
}
};
免责声明:我没有测试它,但它应该基于类似的examples