pdfbox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From til...@apache.org
Subject svn commit: r1846738 - in /pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature: SigUtils.java cert/CRLVerifier.java validation/AddValidationInformation.java validation/CertInformationCollector.java
Date Fri, 16 Nov 2018 18:25:23 GMT
Author: tilman
Date: Fri Nov 16 18:25:23 2018
New Revision: 1846738

URL: http://svn.apache.org/viewvc?rev=1846738&view=rev
Log:
PDFBOX-4381: perform CRL check for revocation at signing time + refactor

Modified:
    pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/SigUtils.java
    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/validation/AddValidationInformation.java
    pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/validation/CertInformationCollector.java

Modified: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/SigUtils.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/SigUtils.java?rev=1846738&r1=1846737&r2=1846738&view=diff
==============================================================================
--- pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/SigUtils.java
(original)
+++ pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/SigUtils.java
Fri Nov 16 18:25:23 2018
@@ -16,9 +16,12 @@
 
 package org.apache.pdfbox.examples.signature;
 
+import java.io.IOException;
 import java.security.cert.CertificateParsingException;
 import java.security.cert.X509Certificate;
 import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.pdfbox.cos.COSArray;
@@ -188,4 +191,31 @@ public class SigUtils
             LOG.error("Certificate extended key usage does not include timeStamping");
         }
     }
+
+    /**
+     * Gets the last relevant signature in the document, i.e. the one with the highest offset.
+     * 
+     * @param document to get its last signature
+     * @return last signature or null when none found
+     * @throws IOException
+     */
+    public static PDSignature getLastRelevantSignature(PDDocument document) throws IOException
+    {
+        SortedMap<Integer, PDSignature> sortedMap = new TreeMap<>();
+        for (PDSignature signature : document.getSignatureDictionaries())
+        {
+            int sigOffset = signature.getByteRange()[1];
+            sortedMap.put(sigOffset, signature);
+        }
+        if (sortedMap.size() > 0)
+        {
+            PDSignature lastSignature = sortedMap.get(sortedMap.lastKey());
+            COSBase type = lastSignature.getCOSObject().getItem(COSName.TYPE);
+            if (type.equals(COSName.SIG) || type.equals(COSName.DOC_TIME_STAMP))
+            {
+                return lastSignature;
+            }
+        }
+        return null;
+    }
 }

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=1846738&r1=1846737&r2=1846738&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
Fri Nov 16 18:25:23 2018
@@ -114,23 +114,8 @@ public final class CRLVerifier
                             crlDistributionPointsURL + " could not be verified");
                 }
                 crl.verify(issuerKey);
-                X509CRLEntry revokedCRLEntry = crl.getRevokedCertificate(cert);
-                if (revokedCRLEntry != null &&
-                    revokedCRLEntry.getRevocationDate().compareTo(signDate) <= 0)
-                {
-                    throw new CertificateVerificationException(
-                            "The certificate was revoked by CRL " +
-                            crlDistributionPointsURL + " on " + revokedCRLEntry.getRevocationDate());
-                }
-                else if (revokedCRLEntry != null)
-                {
-                    LOG.info("The certificate was revoked after signing by CRL " +
-                            crlDistributionPointsURL + " on " + revokedCRLEntry.getRevocationDate());
-                }
-                else
-                {
-                    LOG.info("The certificate was not revoked by CRL " + crlDistributionPointsURL);
-                }
+
+                checkRevocation(crl, cert, signDate, crlDistributionPointsURL);
 
                 // https://tools.ietf.org/html/rfc5280#section-4.2.1.13
                 // If the DistributionPointName contains multiple values,
@@ -156,8 +141,41 @@ public final class CRLVerifier
     }
 
     /**
-     * Downloads CRL from given URL. Supports http, https, ftp and ldap based
-     * URLs.
+     * Check whether the certificate was revoked at signing time.
+     *
+     * @param crl certificate revocation list
+     * @param cert certificate to be checked
+     * @param signDate date the certificate was used for signing
+     * @param crlDistributionPointsURL URL for log message or exception text
+     * @throws CertificateVerificationException if the certificate was revoked at signing
time
+     */
+    public static void checkRevocation
+        (X509CRL crl, X509Certificate cert, Date signDate, String crlDistributionPointsURL)
+                throws CertificateVerificationException
+    {
+        //TODO this should throw a RevokedCertificateException
+        // and these exceptions should go to "cert" package
+        X509CRLEntry revokedCRLEntry = crl.getRevokedCertificate(cert);
+        if (revokedCRLEntry != null &&
+                revokedCRLEntry.getRevocationDate().compareTo(signDate) <= 0)
+        {
+            throw new CertificateVerificationException(
+                    "The certificate was revoked by CRL " +
+                            crlDistributionPointsURL + " on " + revokedCRLEntry.getRevocationDate());
+        }
+        else if (revokedCRLEntry != null)
+        {
+            LOG.info("The certificate was revoked after signing by CRL " +
+                    crlDistributionPointsURL + " on " + revokedCRLEntry.getRevocationDate());
+        }
+        else
+        {
+            LOG.info("The certificate was not revoked by CRL " + crlDistributionPointsURL);
+        }
+    }
+
+    /**
+     * Downloads CRL from given URL. Supports http, https, ftp and ldap based URLs.
      */
     private static X509CRL downloadCRL(String crlURL) throws IOException,
             CertificateException, CRLException,
@@ -212,7 +230,7 @@ public final class CRLVerifier
      * Downloads a CRL from given HTTP/HTTPS/FTP URL, e.g.
      * http://crl.infonotary.com/crl/identity-ca.crl
      */
-    private static X509CRL downloadCRLFromWeb(String crlURL)
+    public static X509CRL downloadCRLFromWeb(String crlURL)
             throws IOException, CertificateException, CRLException
     {
         try (InputStream crlStream = new URL(crlURL).openStream())

Modified: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/validation/AddValidationInformation.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/validation/AddValidationInformation.java?rev=1846738&r1=1846737&r2=1846738&view=diff
==============================================================================
--- pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/validation/AddValidationInformation.java
(original)
+++ pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/validation/AddValidationInformation.java
Fri Nov 16 18:25:23 2018
@@ -26,7 +26,9 @@ import java.math.BigInteger;
 import java.security.GeneralSecurityException;
 import java.security.cert.CRLException;
 import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509CRL;
 import java.security.cert.X509Certificate;
+import java.util.Calendar;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -38,9 +40,13 @@ import org.apache.pdfbox.cos.COSDictiona
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSStream;
 import org.apache.pdfbox.cos.COSUpdateInfo;
+import org.apache.pdfbox.examples.signature.SigUtils;
+import org.apache.pdfbox.examples.signature.cert.CRLVerifier;
+import org.apache.pdfbox.examples.signature.cert.CertificateVerificationException;
 import org.apache.pdfbox.examples.signature.validation.CertInformationCollector.CertSignatureInformation;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
+import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
 import org.bouncycastle.cert.ocsp.BasicOCSPResp;
 import org.bouncycastle.cert.ocsp.OCSPException;
 import org.bouncycastle.cert.ocsp.OCSPResp;
@@ -66,6 +72,7 @@ public class AddValidationInformation
     private COSArray certs;
     private PDDocument document;
     private final Set<BigInteger> foundRevocationInformation = new HashSet<>();
+    Calendar signDate;
 
     /**
      * Signs the given PDF file.
@@ -90,9 +97,9 @@ public class AddValidationInformation
     }
 
     /**
-     * Fetches certificate information from the last signature of the document and appends
a DSS with the validation
-     * information to the document.
-     * 
+     * Fetches certificate information from the last signature of the document and appends
a DSS
+     * with the validation information to the document.
+     *
      * @param document containing the Signature
      * @param filename in file to extract signature
      * @param output where to write the changed document
@@ -101,10 +108,15 @@ public class AddValidationInformation
     private void doValidation(String filename, OutputStream output) throws IOException
     {
         certInformationHelper = new CertInformationCollector();
-        CertSignatureInformation certInfo;
+        CertSignatureInformation certInfo = null;
         try
         {
-            certInfo = certInformationHelper.getLastCertInfo(document, filename);
+            PDSignature signature = SigUtils.getLastRelevantSignature(document);
+            if (signature != null)
+            {
+                certInfo = certInformationHelper.getLastCertInfo(signature, filename);
+                signDate = signature.getSignDate();
+            }
         }
         catch (CertificateProccessingException e)
         {
@@ -298,7 +310,7 @@ public class AddValidationInformation
         {
             addCrlRevocationInfo(certInfo);
         }
-        catch (GeneralSecurityException | IOException | RevokedCertificateException e)
+        catch (GeneralSecurityException | IOException | RevokedCertificateException | CertificateVerificationException
e)
         {
             LOG.warn("Failed fetching CRL", e);
             throw new IOException(e);
@@ -344,11 +356,13 @@ public class AddValidationInformation
      * @throws RevokedCertificateException
      */
     private void addCrlRevocationInfo(CertSignatureInformation certInfo)
-            throws IOException, RevokedCertificateException, GeneralSecurityException
+            throws IOException, RevokedCertificateException, GeneralSecurityException,
+            CertificateVerificationException
     {
-        byte[] crlData = CrlHelper.performCrlRequestAndCheck(certInfo.getCrlUrl(),
-                certInfo.getCertificate(), certInfo.getIssuerCertificate().getPublicKey());
-        COSStream crlStream = writeDataToStream(crlData);
+        X509CRL crl = CRLVerifier.downloadCRLFromWeb(certInfo.getCrlUrl());
+        crl.verify(certInfo.getIssuerCertificate().getPublicKey());
+        CRLVerifier.checkRevocation(crl, certInfo.getCertificate(), signDate.getTime(), certInfo.getCrlUrl());
+        COSStream crlStream = writeDataToStream(crl.getEncoded());
         crls.add(crlStream);
         if (correspondingCRLs != null)
         {
@@ -380,10 +394,10 @@ public class AddValidationInformation
     }
 
     /**
-     * Creates a FlateDecoded <code>COSStream</code> element with the given data.
+     * Creates a Flate encoded <code>COSStream</code> object with the given data.
      * 
-     * @param data to write into the element
-     * @return COSStream Element, that can be added to the document
+     * @param data to write into the COSStream
+     * @return COSStream a COSStream object that can be added to the document
      * @throws IOException
      */
     private COSStream writeDataToStream(byte[] data) throws IOException

Modified: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/validation/CertInformationCollector.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/validation/CertInformationCollector.java?rev=1846738&r1=1846737&r2=1846738&view=diff
==============================================================================
--- pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/validation/CertInformationCollector.java
(original)
+++ pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/signature/validation/CertInformationCollector.java
Fri Nov 16 18:25:23 2018
@@ -74,54 +74,22 @@ public class CertInformationCollector
     private CertSignatureInformation rootCertInfo;
 
     /**
-     * Gets the Certificate Information of the last Signature.
+     * Gets the certificate information of a signature.
      * 
-     * @param document to get the Signature from
+     * @param PDSignature the signature of the document.
      * @param fileName of the document.
      * @return the CertSignatureInformation containing all certificate information
      * @throws CertificateProccessingException when there is an error processing the certificates
      * @throws IOException on a data processing error
      */
-    public CertSignatureInformation getLastCertInfo(PDDocument document, String fileName)
+    public CertSignatureInformation getLastCertInfo(PDSignature signature, String fileName)
             throws CertificateProccessingException, IOException
     {
-        PDSignature signature = getLastRelevantSignature(document);
-        if (signature != null)
+        try (FileInputStream documentInput = new FileInputStream(fileName))
         {
-            try (FileInputStream documentInput = new FileInputStream(fileName))
-            {
-                byte[] signatureContent = signature.getContents(documentInput);
-                return getCertInfo(signatureContent);
-            }
+            byte[] signatureContent = signature.getContents(documentInput);
+            return getCertInfo(signatureContent);
         }
-        return null;
-    }
-
-    /**
-     * Gets the last relevant signature in the document, i.e. the one with the highest offset.
-     * 
-     * @param document to get its last Signature
-     * @return last signature or null when none found
-     * @throws IOException
-     */
-    private PDSignature getLastRelevantSignature(PDDocument document) throws IOException
-    {
-        SortedMap<Integer, PDSignature> sortedMap = new TreeMap<>();
-        for (PDSignature signature : document.getSignatureDictionaries())
-        {
-            int sigOffset = signature.getByteRange()[1];
-            sortedMap.put(sigOffset, signature);
-        }
-        if (sortedMap.size() > 0)
-        {
-            PDSignature lastSignature = sortedMap.get(sortedMap.lastKey());
-            COSBase type = lastSignature.getCOSObject().getItem(COSName.TYPE);
-            if (type.equals(COSName.SIG) || type.equals(COSName.DOC_TIME_STAMP))
-            {
-                return lastSignature;
-            }
-        }
-        return null;
     }
 
     /**



Mime
View raw message