X509CertSelector selector = new X509CertSelector();
selector.setCertificate(certificate);
PKIXBuilderParameters parameters = new PKIXBuilderParameters(anchors, selector);
parameters.setMaxPathLength(-1);
parameters.addCertStore(CertStore.getInstance("Collection",
new CollectionCertStoreParameters(Collections.singletonList(certificate))));
if (intermediateCertificates != null) {
parameters.addCertStore(CertStore.getInstance("Collection",
new CollectionCertStoreParameters(intermediateCertificates)));
}
parameters.setRevocationEnabled(false);
// Build a certificate path.
CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
CertPath path = builder.build(parameters).getCertPath();
if (disableRevocationCheck) {
// Disable revocatin check.
parameters.setRevocationEnabled(false);
} else {
// Enable revocation check.
parameters.setRevocationEnabled(true);
// Select a method to check revocation status.
boolean useOCSP = OCSPClient.getOCSPURLs(certificate).size() > 0;
boolean useCRL = CRLDownloader.getCRLDistributionPoints(certificate).size() > 0;
if (!useOCSP && !useCRL) {
throw new NoRevocationStatusException(
String.format(messages.getString(
"Certificate_has_no_method_to_verify_revocation_status__%s"),
CertificateValidator.getCertificateName(certificate)));
}
// Select online or offline revocation check.
if (date == null) {
// Enable online revocation check.
Security.setProperty("ocsp.enable", "true");
// Correct problem with enableCRLDP system property.
// Once enableCRLDP is true, it cannot be disabled.
// Must manually download all CRLs.
System.setProperty("com.sun.security.enableCRLDP", "false");
// Download manually CRLs.
Collection<? extends Certificate> certificates = path.getCertificates();
ArrayList<X509CRL> crls = new ArrayList<X509CRL>();
for (Certificate c : certificates) {
X509CRL crl = CRLDownloader.getCRL((X509Certificate) c);
if (crl != null) {
crls.add(crl);
}
}
parameters.addCertStore(CertStore.getInstance("Collection",
new CollectionCertStoreParameters(crls)));
} else {
// Enable validation on a previous date.
parameters.setDate(date.getTime());
// Disable online revocation check.
Security.setProperty("ocsp.enable", "false");
System.setProperty("com.sun.security.enableCRLDP", "false");
// Determine the issuer certificate.
X509Certificate issuerCertificate = null;
if (path.getCertificates().size() > 1) {
// Assign the next certificate in chain as the issuer.
issuerCertificate = (X509Certificate) path.getCertificates().get(1);
} else {
// Check if a root certificate is the issuer.
for (X509Certificate rootCertificate : rootCertificates) {
try {
certificate.verify(rootCertificate.getPublicKey());
issuerCertificate = rootCertificate;
break;
} catch (Exception exception) {
// Try the next root certificate.
continue;
}
}
}
// Perform offline revocation check using stored OCSP responses.
if (useOCSP) {
// Check if offline OCSP responses were provided.
if (ocspResponses == null) {
throw new NoOCSPResponseException(
String.format(messages.getString(
"No_OCSP_response_was_provided_to_perform_offline_revocation_check_of_the_certificate__%s"),
CertificateValidator.getCertificateName(certificate)));
}
// Disable standard online revocation check.
parameters.setRevocationEnabled(false);
// Verify the certificate using OCSP responses.
OCSPVerifier verifier = new OCSPVerifier(null, (ArrayList<BasicOCSPResp>) ocspResponses);
verifier.setOnlineCheckingAllowed(false);
if (verifier.verify(certificate, issuerCertificate, date.getTime()).size() == 0) {
throw new NoOCSPResponseException(
String.format(messages.getString(
"Could_not_find_a_valid_OCSP_response_for_the_certificate__%s"),
CertificateValidator.getCertificateName(certificate)));
}
// Enable offline revocation check using CRL.
} else if (useCRL) {
// Check if CRLs were provided.
if (certificateRevocationLists == null) {
throw new NoCRLException(
String.format(messages.getString(
"No_certificate_revocation_list_was_provided_to_perform_offline_revocation_check_of_the_certificate__%s"),
CertificateValidator.getCertificateName(certificate)));
}
// Add CRLs to perform offline revocation check.
parameters.addCertStore(CertStore.getInstance("Collection",
new CollectionCertStoreParameters(certificateRevocationLists)));
}
// If it is necessary to verify OCSP responses offline,
// validate recursively the certificate chain.
if (ocspResponses != null && ocspResponses.size() > 0