2

我正在尝试使用 Java从用户证书和 CA 证书CertPathBuilder创建,但我收到CertPath

Exception in thread "main" sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
    at CertPathBuilderTest.main(CertPathBuilderTest.java:63)

当我启用了吊销检查(使用.setRevocationEnabled(true))。所以看起来 Java 拒绝证书或 CRL,即使我可以使用 OpenSSL 和 gnupg 毫无问题地验证它们。

CA 结构是最简单的:只有 CA 签名证书和 CRL,没有中间 CA。

有问题的证书:cacerts.jksprivate.jks

示例程序:

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CRL;
import java.security.cert.CRLException;
import java.security.cert.CertPath;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertPathBuilderResult;
import java.security.cert.CertStore;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.X509CRL;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

public class CertPathBuilderTest {

/**
 * @param args
 * @throws IOException 
 * @throws CertificateException 
 * @throws NoSuchAlgorithmException 
 * @throws KeyStoreException 
 * @throws CRLException 
 * @throws InvalidAlgorithmParameterException 
 * @throws UnexpectedJCAException 
 * @throws SigningCertChainException 
 * @throws CertPathBuilderException 
 */
public static void main(String[] args) 
        throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, CRLException, InvalidAlgorithmParameterException, CertPathBuilderException
{
    // TODO Auto-generated method stub
    // keytool -importcert -file CA.pem -keystore cacerts.jks -storepass changeit
    KeyStore trustAnchors = loadJKSKeyStore("cacerts.jks", "changeit");
    KeyStore myKeyStore = loadJKSKeyStore("private.jks", "changeit");

    String crlLocation = "http://crl.qbs.com.pl/QBSJanKuban.crl";
    X509CRL crl = downloadCRL(crlLocation);

    CertStore cs = otherCertificatesCertStore(trustAnchors, myKeyStore, crl);
    ///*
    CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
    X509CertSelector certSelector = new X509CertSelector();
    certSelector.setCertificate((X509Certificate) myKeyStore.getCertificate("mykey"));
    PKIXBuilderParameters cpp = new PKIXBuilderParameters(trustAnchors, certSelector);
    cpp.addCertStore(cs);
    cpp.setRevocationEnabled(true);
    cpp.setMaxPathLength(6);
    cpp.setDate(new Date());

    CertPathBuilderResult a = cpb.build(cpp);
    CertPath certPath = a.getCertPath();
}

private static KeyStore loadJKSKeyStore(String path, String password)
    throws KeyStoreException,
    NoSuchAlgorithmException, CertificateException, IOException
{
    FileInputStream fis = new FileInputStream(path);
    KeyStore ks = KeyStore.getInstance("jks");
    ks.load(fis, password.toCharArray());
    fis.close();
    return ks;
}

private static X509CRL downloadCRL(String crlLocation)
        throws IOException, CertificateException, CRLException
{
    URL crlURL = new URL(crlLocation);
    BufferedInputStream in = new BufferedInputStream(crlURL.openStream());

    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    CRL crl = cf.generateCRL(in);

    return (X509CRL) crl;
}

private static CertStore otherCertificatesCertStore(KeyStore trustAnchors,
        KeyStore myCerts, X509CRL... crl)
        throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, KeyStoreException
{

    CertStore cs;

    Collection<Object> contentList = new ArrayList<Object>();
    contentList.add(trustAnchors.getCertificate("qbsca"));
    contentList.add(myCerts.getCertificate("mykey"));
    for (int i=0; i < crl.length; i++) {
        contentList.add(crl[i]);
    }
    cs = CertStore.getInstance("Collection", new CollectionCertStoreParameters(contentList));

    return cs;
}
}
4

1 回答 1

2

问题是由 SUN 和 BC 加密提供程序中的错误(?)引起的。

当用户证书不仅CRL Distribution Point以 URI 的形式指定,而且CRL IssuerCertPathBuilder 无法验证 CRL 的有效性,整个过程失败。

解决方法是创建缺少此扩展的证书。

于 2012-08-21T12:53:22.353 回答