Author: tilman Date: Tue Oct 16 15:51:26 2018 New Revision: 1844025 URL: http://svn.apache.org/viewvc?rev=1844025&view=rev Log: PDFBOX-3017: verify CRL against certificate; use signing date when verifying the certification chain
Modified: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/cert/CRLVerifier.java pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/cert/CertificateVerifier.java Modified: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/cert/CRLVerifier.java URL: http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/cert/CRLVerifier.java?rev=1844025&r1=1844024&r2=1844025&view=diff ============================================================================== --- pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/cert/CRLVerifier.java (original) +++ pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/cert/CRLVerifier.java Tue Oct 16 15:51:26 2018 @@ -23,6 +23,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.security.PublicKey; import java.security.cert.CRLException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; @@ -33,6 +34,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.Hashtable; import java.util.List; +import java.util.Set; import javax.naming.Context; import javax.naming.NamingException; @@ -74,9 +76,13 @@ public final class CRLVerifier * * @param cert the certificate to be checked for revocation * @param signDate the date when the signing took place + * @param additionalCerts set of trusted root CA certificates that will be + * used as "trust anchors" and intermediate CA certificates that will be + * used as part of the certification chain. * @throws CertificateVerificationException if the certificate is revoked */ - public static void verifyCertificateCRLs(X509Certificate cert, Date signDate) + public static void verifyCertificateCRLs(X509Certificate cert, Date signDate, + Set<X509Certificate> additionalCerts) throws CertificateVerificationException { try @@ -86,9 +92,27 @@ public final class CRLVerifier { LOG.info("Checking distribution point URL: " + crlDistributionPointsURL); X509CRL crl = downloadCRL(crlDistributionPointsURL); - //TODO verify CRL, see wikipedia: + + // Verify CRL, see wikipedia: // "To validate a specific CRL prior to relying on it, // the certificate of its corresponding CA is needed" + PublicKey issuerKey = null; + for (X509Certificate additionalCert : additionalCerts) + { + if (crl.getIssuerX500Principal().equals( + additionalCert.getSubjectX500Principal())) + { + issuerKey = additionalCert.getPublicKey(); + } + } + if (issuerKey == null) + { + throw new CertificateVerificationException( + "Certificate for " + crl.getIssuerX500Principal() + + "not found in certificate chain, so the CRL at " + + crlDistributionPointsURL + " could not be verified"); + } + crl.verify(issuerKey); X509CRLEntry revokedCRLEntry = crl.getRevokedCertificate(cert); if (revokedCRLEntry != null && revokedCRLEntry.getRevocationDate().compareTo(signDate) <= 0) Modified: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/cert/CertificateVerifier.java URL: http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/cert/CertificateVerifier.java?rev=1844025&r1=1844024&r2=1844025&view=diff ============================================================================== --- pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/cert/CertificateVerifier.java (original) +++ pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/cert/CertificateVerifier.java Tue Oct 16 15:51:26 2018 @@ -105,11 +105,11 @@ public final class CertificateVerifier // Attempt to build the certification chain and verify it PKIXCertPathBuilderResult verifiedCertChain = verifyCertificate( - cert, trustedRootCerts, intermediateCerts); + cert, trustedRootCerts, intermediateCerts, signDate); // Check whether the certificate is revoked by the CRL // given in its CRL distribution point extension - CRLVerifier.verifyCertificateCRLs(cert, signDate); + CRLVerifier.verifyCertificateCRLs(cert, signDate, additionalCerts); // The chain is built and verified. Return it as a result return verifiedCertChain; @@ -163,6 +163,7 @@ public final class CertificateVerifier * @param cert - certificate for validation * @param trustedRootCerts - set of trusted root CA certificates * @param intermediateCerts - set of intermediate certificates + * @param signDate the date when the signing took place * @return the certification chain (if verification is successful) * @throws GeneralSecurityException - if the verification is not successful * (e.g. certification path cannot be built or some certificate in the chain @@ -170,9 +171,9 @@ public final class CertificateVerifier */ private static PKIXCertPathBuilderResult verifyCertificate( X509Certificate cert, Set<X509Certificate> trustedRootCerts, - Set<X509Certificate> intermediateCerts) throws GeneralSecurityException + Set<X509Certificate> intermediateCerts, Date signDate) + throws GeneralSecurityException { - // Create the selector that specifies the starting certificate X509CertSelector selector = new X509CertSelector(); selector.setCertificate(cert); @@ -190,12 +191,18 @@ public final class CertificateVerifier // Disable CRL checks (this is done manually as additional step) pkixParams.setRevocationEnabled(false); + pkixParams.setDate(signDate); + // Specify a list of intermediate certificates CertStore intermediateCertStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(intermediateCerts)); pkixParams.addCertStore(intermediateCertStore); // Build and verify the certification chain + // If this doesn't work although it should, it can be debugged + // by starting java with -Djava.security.debug=certpath + // see also + // https://docs.oracle.com/javase/8/docs/technotes/guides/security/troubleshooting-security.html CertPathBuilder builder = CertPathBuilder.getInstance("PKIX"); return (PKIXCertPathBuilderResult) builder.build(pkixParams); }