从终端实体获取根证书和中间证书 [英] Getting root and intermediate certificates from an end-entity

查看:543
本文介绍了从终端实体获取根证书和中间证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我仍然是密码学的新手,我每天都偶然发现一些简单的东西。今天只是那些日子之一。

still being a noob in cryptography I stumble upon simple things every day. And today is just one of those days.

我想用有弹性的城堡库在Java中验证smime消息,我想我几乎想通了,但是问题是此刻是PKIXparameters对象的构建。
假设我有一个具有以下结构的最终实体x509证书:

I want to validate smime messages in java with the bouncy castle library, and I think I almost figured it out, but the problem at this moment is the building of the PKIXparameters object. Let's say, I have an end-entity x509certificate with the following structure:

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

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

In order to validate message I need to build a chain of trust first, but I cannot figure out how to extract a root and intermediate certificates from the end-entity.

我尝试使用end -entity作为根,但没有用:

I tried to use end-entity as root but it didn't work:

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.

顺便说一句,我可以只使用终端实体证书来验证消息吗,就像

And btw, can I just use only the end-entity certificate to validate messages, as if it were the self-signed certificate?

推荐答案

我已使用 BouncyCastle 1.56 进行了此测试。

I've used BouncyCastle 1.56 for this test.

从最终实体获得发行人证书的一种方法是查找 权威信息访问扩展名

One way to get the issuer's certificate from the end entity is to look for the Authority Information Access extension.

此扩展名可能 >存在(不是强制性的),并且可能包含用于获取颁发者证书的URL(颁发者是当前证书之上的证书,因此最终实体的颁发者为

This extension may be present (it's not mandatory) and may contain the URL to get the issuer's certificate (issuer is the certificate "above" the current one, so the end entity's issuer is the intermediate, and the intermediate's issuer is the root).

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

You can get this extension value with 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());
        }
    }
}

因此您可以使用此代码与最终实体证书一起获得中间体。

So you can use this code with the end entity certificate to get the intermediate. Then you use it again with the intermediate to get the root.

然后将 root 添加到 TrustAnchor ,并且验证应该起作用。

Then you add the root to your TrustAnchor and the validation should work.

注意:说,此扩展名不是强制性的,可能不存在。在这种情况下, getExtensionValue 将返回 null ,我知道的唯一替代方法是在google中搜索证书并下载它们(那些证书链通常是公开的,并不难找到)

Note: But as I said, this extension is not mandatory and may not be present. In this case, getExtensionValue will return null, and the only alternative that I know is to search for the certificates in google and download them (those certificate chains are usually public and not hard to find)

这篇关于从终端实体获取根证书和中间证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆