java找不到根证书和中间证书,从终端实体获取根证书和中间证书

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

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.

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());

}

Got this exception:

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?

解决方案

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.

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).

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.

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

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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值