Java Can';t使用CertPathBuilder构建CertPath

Java Can';t使用CertPathBuilder构建CertPath,java,cryptography,Java,Cryptography,我试图使用JavaCertPathBuilder从用户证书和CA证书创建CertPath,但我收到 Exception in thread "main" sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuil

我试图使用Java
CertPathBuilder
从用户证书和CA证书创建
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

有问题的证书:以及

示例程序:

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;
}
}
import java.io.BufferedInputStream;
导入java.io.FileInputStream;
导入java.io.IOException;
导入java.net.URL;
导入java.security.invalidalgorithParameterException;
导入java.security.KeyStore;
导入java.security.KeyStoreException;
导入java.security.NoSuchAlgorithmException;
导入java.security.cert.CRL;
导入java.security.cert.CRLException;
导入java.security.cert.CertPath;
导入java.security.cert.CertPathBuilder;
导入java.security.cert.CertPathBuilderException;
导入java.security.cert.CertPathBuilderResult;
导入java.security.cert.CertStore;
导入java.security.cert.CertificateException;
导入java.security.cert.CertificateFactory;
导入java.security.cert.CollectionCertStoreParameters;
导入java.security.cert.pkixbuilder参数;
导入java.security.cert.X509CRL;
导入java.security.cert.X509CertSelector;
导入java.security.cert.x509证书;
导入java.util.ArrayList;
导入java.util.Collection;
导入java.util.Date;
公共类CertPathBuilderTest{
/**
*@param args
*@抛出异常
*@CertificateException
*@NoSuchAlgorithmException
*@KeyStoreException
*@CRLException
*@InvalidalgorithParameterException
*@抛出意外的JCAEException
*@抛出SigningCertChainException
*@CertPathBuilderException
*/
公共静态void main(字符串[]args)
抛出KeyStoreException、NoSuchAlgorithmException、CertificateException、IOException、CrlexException、InvalidAlgorithmParameterException、CertPathBuilderException
{
//TODO自动生成的方法存根
//keytool-importcert-file CA.pem-keystore cacerts.jks-storepass changeit
keystoretrustanchors=loadJKSKeyStore(“cacerts.jks”,“changeit”);
KeyStore myKeyStore=loadJKSKeyStore(“private.jks”,“changeit”);
字符串crlLocation=”http://crl.qbs.com.pl/QBSJanKuban.crl";
X509CRL crl=下载crl(crlLocation);
CertStore cs=其他CertificateScertStore(信任锚、myKeyStore、crl);
///*
CertPathBuilder cpb=CertPathBuilder.getInstance(“PKIX”);
X509CertSelector certSelector=新的X509CertSelector();
certSelector.setCertificate((X509Certificate)myKeyStore.getCertificate(“mykey”);
PKIXBuilderParameters cpp=新的PKIXBuilderParameters(信任锚、证书选择器);
cpp.addCertStore(cs);
cpp.setRevocationEnabled(真);
cpp.setMaxPathLength(6);
设置日期(新日期());
CertPathBuilderResult a=cpb.build(cpp);
CertPath CertPath=a.getCertPath();
}
私有静态密钥库loadJKSKeyStore(字符串路径、字符串密码)
这是一个例外,
NoSuchAlgorithmException、CertificateException、IOException
{
FileInputStream fis=新的FileInputStream(路径);
KeyStore ks=KeyStore.getInstance(“jks”);
加载(fis,password.toCharArray());
fis.close();
返回ks;
}
私有静态X509CRL下载CRL(字符串分配)
抛出IOException、CertificateException、CrlexException
{
URL crlURL=新URL(crlLocation);
BufferedInputStream in=新的BufferedInputStream(crlURL.openStream());
CertificateFactory cf=CertificateFactory.getInstance(“X.509”);
CRL CRL=cf.generateCRL(in);
返回(X509CRL)crl;
}
私有静态CertStore otherCertificatesCertStore(密钥库信任锚,
KeyStore myCerts,X509CRL…crl)
抛出InvalidAlgorithmParameterException、NoSuchAlgorithmException、KeyStoreException
{
CertStore cs;
集合内容列表=新的ArrayList();
add(trustAnchors.getCertificate(“qbsca”);
add(myCerts.getCertificate(“mykey”);
对于(int i=0;i
问题是由SUN和BC加密提供程序中的错误(?)引起的

当用户证书不仅以URI的形式指定了
CRL分发点
,而且还指定了
CRL颁发者
时,CertPathBuilder无法验证CRL的有效性,整个过程失败


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

@owlstead:没问题。如果我发现了问题,我会尝试发布问题的解决方案,我很清楚发现“我发现了”或者没有答案是多么令人沮丧。。。