从最终实体获取根证书和中间证书

2024-06-20

作为密码学的菜鸟,我每天都会偶然发现一些简单的事情。今天只是那些日子之一。

我想用 bouncy castle 库验证 java 中的 smime 消息,我想我几乎已经弄清楚了,但此时的问题是 PKIXparameters 对象的构建。 假设我有一个具有以下结构的最终实体 x509 证书:

root certificate
 +->intermediate certificate
    +->end-entity certificate

为了验证消息,我需要首先构建信任链,但我无法弄清楚如何从最终实体提取根证书和中间证书。

我尝试使用最终实体作为根,但它不起作用:

InputStream isCert = GetFISCertificate();

List list = new ArrayList();
X509Certificate rootCert = (X509Certificate) certificateFactory.generateCertificate(isCert);
list.add(rootCert);
CollectionCertStoreParameters params = new CollectionCertStoreParameters(list);
CertStore store = CertStore.getInstance("Collection", params, BC);

//create cert path
List certChain = new ArrayList();
certChain.add(rootCert);
CertPath certPath = certificateFactory.generateCertPath(certChain);
Set trust = Collections.singleton(new TrustAnchor(rootCert, null));

//validation
CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX", BC);
PKIXParameters pKIXParameters = new PKIXParameters(trust);
pKIXParameters.addCertStore(store);
pKIXParameters.setDate(new Date());
try {
CertPathValidatorResult result = certPathValidator.validate(certPath, pKIXParameters);
System.out.println("certificate path validated");

} catch (CertPathValidatorException e) {
System.out.println("validation failed on certificate number " + e.getIndex() + ", details: " + e.getMessage());
}

得到这个异常:

validation failed on certificate number -1, details: Trust anchor for certification path not found.

顺便说一句,我可以只使用最终实体证书来验证消息,就像它是自签名证书一样吗?


我用过充气城堡 1.56对于这个测试。

从最终实体获取颁发者证书的一种方法是查找权威信息获取扩大 https://www.rfc-editor.org/rfc/rfc5280#section-4.2.2.1.

这个扩展may出席(这不是强制性的)并且may包含获取颁发者证书的 URL (issuer是当前证书“之上”的证书,因此最终实体的颁发者是中间实体,而中间实体的颁发者是根)。

您可以使用 BouncyCastle 获取此扩展值:

import java.security.cert.X509Certificate;
import org.bouncycastle.asn1.x509.AccessDescription;
import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.x509.extension.X509ExtensionUtil;

X509Certificate cert = // end entity certificate

// get Authority Information Access extension (will be null if extension is not present)
byte[] extVal = cert.getExtensionValue(Extension.authorityInfoAccess.getId());
AuthorityInformationAccess aia = AuthorityInformationAccess.getInstance(X509ExtensionUtil.fromExtensionValue(extVal));

// check if there is a URL to issuer's certificate
AccessDescription[] descriptions = aia.getAccessDescriptions();
for (AccessDescription ad : descriptions) {
    // check if it's a URL to issuer's certificate
    if (ad.getAccessMethod().equals(X509ObjectIdentifiers.id_ad_caIssuers)) {
        GeneralName location = ad.getAccessLocation();
        if (location.getTagNo() == GeneralName.uniformResourceIdentifier) {
            String issuerUrl = location.getName().toString();
            // http URL to issuer (test in your browser to see if it's a valid certificate)
            // you can use java.net.URL.openStream() to create a InputStream and create
            // the certificate with your CertificateFactory
            URL url = new URL(issuerUrl);
            X509Certificate issuer = (X509Certificate) certificateFactory.generateCertificate(url.openStream());
        }
    }
}

因此,您可以将此代码与最终实体证书一起使用来获取中间体。然后你再次将它与中间体一起使用以获得根。

然后你添加root给你的TrustAnchor并且验证应该有效。


Note:但正如我所说,此扩展不是强制性的,也可能不存在。在这种情况下,getExtensionValue将返回null,我知道的唯一选择是在谷歌中搜索证书并下载它们(这些证书链通常是公开的并且不难找到)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从最终实体获取根证书和中间证书 的相关文章

随机推荐