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:
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 returnnull
, 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)btw, if we have out certificate installed in windows, everything is much simpler:
boom, and the whole certificates chain is ready