I am trying to verify a chain of certificates that I have generated on my own, and I seem to get correct results but I am unsure if I am doing it the right way.
Say I have a chain of Intermediate -> Intermediate -> Leaf. I don't care about the root, I want to verify up to a certain point in a chain. This could be the root, or just a snippet of a longer chain, provided that it is intact.
To clarify; I want to verify that chain regardless of the ultimate root. Root -> Intermediate 1 -> Intermediate 2 -> Leaf should be valid, as well as only Intermediate 1 -> Intermediate 2 -> Leaf. The only difference here should probably (?) be what is considered the TrustAnchor.
To do this, I have followed this Oracle documentation.
Here's my code snippet:
public boolean validateChain(final X509Certificate... certificates) {
try {
final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
final X509Certificate intermediateCertificate = certificates[0];
final X509Certificate leaf = certificates[1];
final List<X509Certificate> path = Collections.singletonList(leaf);
final CertPath certPath = certificateFactory.generateCertPath(path);
Set<TrustAnchor> anchors = new HashSet<>();
anchors.add(new TrustAnchor(intermediateCertificate, null));
final X509Certificate root = this.certificate;
anchors.add(new TrustAnchor(root, null));
PKIXParameters params = new PKIXParameters(anchors);
params.setRevocationEnabled(false);
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
validator.validate(certPath, params);
return true;
} catch (final GeneralSecurityException e) {
LOG.error("Could not validate certificate chain", e);
}
return false;
}
Never mind the rudimentary array handling, I will improve on that. This implementation assumes a base class of mine has been implemented and that is always the root against which the supplied certificates are validated.
Is this the right way to do it? I don't really understand the distinction between a TrustAnchor and the certificates placed in the CertPath.
If I add the certificate named intermediateCertificate to the construction of the CertPath, the execution fails with:
Caused by: java.security.cert.CertPathValidatorException: subject/issuer name chaining check failed
Say if I wanted to verify a chain with 10 certificates, should only the leaf certificate be placed in the CertPath and all other certificates above in the chain are considered TrustAnchors?
If anyone could shine a light on this distinction I'd be very grateful.
Additional information edit:
I know my chain is valid because I have verified my entire chain using OpenSSL. This is my entire chain, where each file contains only the public part of the certificate.
openssl verify -CAfile root.pem -untrusted intermediate1.pem -untrusted intermediate2.pem leaf.pem
I have also verified a partial chain:
openssl verify -no-CApath -partial_chain -trusted intermediate1.pem -trusted intermediate2.pem leaf.pem
Both of these respond with leaf.pem: OK.