I'm trying to process X509 certificates in several steps and running into a couple of problems. I'm new to JCE so I not completely up to date on everything yet.
We want to be able to parse several different X509 certificates based on different encodings (PEM, DER and PCKS7). I've exported the same certificate from https://belgium.be in PEM and PCKS7 format using FireFox (certificate including chain). I've left couple lines out that are not needed for the questions
public List<X509Certificate> parse(FileInputStream fis) {
/*
* Generate a X509 Certificate initialized with the data read from the inputstream.
* NOTE: Generation fails when using BufferedInputStream on PKCS7 certificates.
*/
List<X509Certificate> certificates = null;
log.debug("Parsing new certificate.");
certificates = (List<X509Certificate>) cf.generateCertificates(fis);
return certificates;
}
This code is working fine aslong as I work with a FileInputStream instead of a BufferedInputStream for PCKS7, which is quite strange already I think? But I can live with it.
The next step is to validate these certificate chains.
1) Check if all certificates have a valid date (easy)
2) Validate certificate chain using OCSP (and fallback to CRL if no OCSP URL is found in the certificate). This is where I'm not completely sure how to handle this.
I'm using the Sun JCE, but it seems there is not that much documentation available (in examples) for this?
I first made a simple implementation that only checks the chain without going through the OCSP/CRL checks.
private Boolean validateChain(List<X509Certificate> certificates) {
PKIXParameters params;
CertPath certPath;
CertPathValidator certPathValidator;
Boolean valid = Boolean.FALSE;
params = new PKIXParameters(keyStore);
params.setRevocationEnabled(false);
certPath = cf.generateCertPath(certificates);
certPathValidator = CertPathValidator.getInstance("PKIX");
PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult)
certPathValidator.validate(certPath, params);
if(null != result) {
valid = Boolean.TRUE;
}
return valid;
}
This is working fine for my PEM certificate, but not for the PCKS7 certificate (same certifcate, only exported in other format).
java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors.
The only difference I'm able to see is that the order in which the CertPath is formed is not the same? I was not able to figure out what was going wrong so I left this for now and kept on going with the PEM certificate, but lets call this QUESTION 1 ;)
What I wanted to implement afterwards was the OCSP checking.
Apparently if I enable OCSP using: Security.setProperty("ocsp.enable", "true"); and set params.setRevocationEnabled(true);
it should be able to find the OCSP URL on its own, but that does not seem to be the case. What is the standard implementation supposed to do (QUESTION 2)?
java.security.cert.CertPathValidatorException: Must specify the location of an OCSP Responder
Going past this, I found a way to retrieve the OCSP url from the certificate using AuthorityInfoAccessExtension and such.
But after setting the OCSP url manually in the ocsp.url property, I'm getting an java.security.cert.CertPathValidatorException: OCSP response error: UNAUTHORIZED
It seems like I'm missing a lot of necessary steps while alot of online references say setting the ocsp.enable property should be all you need to do?
Perhaps any of you whizkids cant guide me through the process a little bit? Show me where I'm completely wrong :)
The next step would be implementing CRL checks if no OCSP was found, if anyone could point out any example or show me some documentation on this it would also be much appreciated!
Thanks!
EDIT:
Since it's not picking up the properties on its own, I've been trying to set all the properties myself using the following:
// Activate OCSP
Security.setProperty("ocsp.enable", "true");
// Activate CRLDP -- no idea what this is
Security.setProperty("com.sun.security.enableCRLDP", "true");
X509Certificate target = (X509Certificate) certPath.getCertificates().get(0);
Security.setProperty("ocsp.responderURL","http://ocsp.pki.belgium.be/");
Security.setProperty("ocsp.responderCertIssuerName", target.getIssuerX500Principal().getName());
Security.setProperty("ocsp.responderCertSubjectName", target.getSubjectX500Principal().getName());
Security.setProperty("ocsp.responderCertSerialNumber", target.getSerialNumber().toString(16));
Which gives an exception:
java.security.cert.CertPathValidatorException: Cannot find the responder's certificate (set using the OCSP security properties).
See Question&Answers more detail:
os