You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2017/03/08 19:36:43 UTC

svn commit: r1786064 - in /pdfbox/branches/2.0: examples/src/main/java/org/apache/pdfbox/examples/signature/ pdfbox/src/main/java/org/apache/pdfbox/cos/

Author: tilman
Date: Wed Mar  8 19:36:43 2017
New Revision: 1786064

URL: http://svn.apache.org/viewvc?rev=1786064&view=rev
Log:
PDFBOX-3017, PDFBOX-3699: check for certification + certify

Modified:
    pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateSignature.java
    pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateSignatureBase.java
    pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateVisibleSignature.java
    pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java

Modified: pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateSignature.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateSignature.java?rev=1786064&r1=1786063&r2=1786064&view=diff
==============================================================================
--- pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateSignature.java (original)
+++ pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateSignature.java Wed Mar  8 19:36:43 2017
@@ -115,6 +115,12 @@ public class CreateSignature extends Cre
     {
         setTsaClient(tsaClient);
 
+        int accessPermissions = getMDPPermission(document);
+        if (accessPermissions == 1)
+        {
+            throw new IllegalStateException("No changes to the document are permitted due to DocMDP transform parameters dictionary");
+        }     
+
         // create signature dictionary
         PDSignature signature = new PDSignature();
         signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
@@ -127,6 +133,12 @@ public class CreateSignature extends Cre
         // the signing date, needed for valid signature
         signature.setSignDate(Calendar.getInstance());
 
+        // Optional: certify 
+        if (accessPermissions == 0)
+        {
+            setMDPPermission(document, signature, 2);
+        }        
+
         if (isExternalSigning())
         {
             System.out.println("Sign externally...");

Modified: pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateSignatureBase.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateSignatureBase.java?rev=1786064&r1=1786063&r2=1786064&view=diff
==============================================================================
--- pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateSignatureBase.java (original)
+++ pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateSignatureBase.java Wed Mar  8 19:36:43 2017
@@ -30,6 +30,12 @@ import java.security.cert.X509Certificat
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
 import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface;
 import org.bouncycastle.asn1.ASN1Encodable;
 import org.bouncycastle.asn1.ASN1EncodableVector;
@@ -254,4 +260,88 @@ public abstract class CreateSignatureBas
     {
         return externalSigning;
     }
+
+    /**
+     * Get the access permissions granted for this document in the DocMDP transform parameters
+     * dictionary. Details are described in the table "Entries in the DocMDP transform parameters
+     * dictionary" in the PDF specification.
+     *
+     * @param doc document.
+     * @return the permission value. 0 means no DocMDP transform parameters dictionary exists. Other
+     * return values are 1, 2 or 3. 2 is also returned if the DocMDP transform parameters dictionary
+     * is found but did not contain a /P entry, or if the value is outside the valid range.
+     */
+    public int getMDPPermission(PDDocument doc)
+    {
+        COSBase base = doc.getDocumentCatalog().getCOSObject().getDictionaryObject(COSName.PERMS);
+        if (base instanceof COSDictionary)
+        {
+            COSDictionary permsDict = (COSDictionary) base;
+            base = permsDict.getDictionaryObject(COSName.DOCMDP);
+            if (base instanceof COSDictionary)
+            {
+                COSDictionary signatureDict = (COSDictionary) base;
+                base = signatureDict.getDictionaryObject("Reference");
+                if (base instanceof COSArray)
+                {
+                    COSArray refArray = (COSArray) base;
+                    for (int i = 0; i < refArray.size(); ++i)
+                    {
+                        base = refArray.getObject(i);
+                        if (base instanceof COSDictionary)
+                        {
+                            COSDictionary sigRefDict = (COSDictionary) base;
+                            if (COSName.DOCMDP.equals(sigRefDict.getDictionaryObject("TransformMethod")))
+                            {
+                                base = sigRefDict.getDictionaryObject("TransformParams");
+                                if (base instanceof COSDictionary)
+                                {
+                                    COSDictionary transformDict = (COSDictionary) base;
+                                    int accessPermissions = transformDict.getInt(COSName.P, 2);
+                                    if (accessPermissions < 1 || accessPermissions > 3)
+                                    {
+                                        accessPermissions = 2;
+                                    }
+                                    return accessPermissions;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return 0;
+    }
+
+    public void setMDPPermission(PDDocument doc, PDSignature signature, int accessPermissions)
+    {
+        COSDictionary sigDict = signature.getCOSObject();
+
+        // DocMDP specific stuff
+        COSDictionary transformParameters = new COSDictionary();
+        transformParameters.setItem(COSName.TYPE, COSName.getPDFName("TransformParams"));
+        transformParameters.setInt(COSName.P, accessPermissions);
+        transformParameters.setName(COSName.V, "1.2");
+        transformParameters.setNeedToBeUpdated(true);
+
+        COSDictionary referenceDict = new COSDictionary();
+        referenceDict.setItem(COSName.TYPE, COSName.getPDFName("SigRef"));
+        referenceDict.setItem("TransformMethod", COSName.getPDFName("DocMDP"));
+        referenceDict.setItem("DigestMethod", COSName.getPDFName("SHA1"));
+        referenceDict.setItem("TransformParams", transformParameters);
+        referenceDict.setNeedToBeUpdated(true);
+
+        COSArray referenceArray = new COSArray();
+        referenceArray.add(referenceDict);
+        sigDict.setItem("Reference", referenceArray);
+        referenceArray.setNeedToBeUpdated(true);
+
+        // Catalog
+        COSDictionary catalogDict = doc.getDocumentCatalog().getCOSObject();
+        COSDictionary permsDict = new COSDictionary();
+        catalogDict.setItem(COSName.PERMS, permsDict);
+        permsDict.setItem(COSName.DOCMDP, signature);
+        catalogDict.setNeedToBeUpdated(true);
+        permsDict.setNeedToBeUpdated(true);
+    }
 }

Modified: pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateVisibleSignature.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateVisibleSignature.java?rev=1786064&r1=1786063&r2=1786064&view=diff
==============================================================================
--- pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateVisibleSignature.java (original)
+++ pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateVisibleSignature.java Wed Mar  8 19:36:43 2017
@@ -144,6 +144,15 @@ public class CreateVisibleSignature exte
         // load document
         PDDocument doc = PDDocument.load(inputFile);
 
+        int accessPermissions = getMDPPermission(doc);
+        if (accessPermissions == 1)
+        {
+            throw new IllegalStateException("No changes to the document are permitted due to DocMDP transform parameters dictionary");
+        }
+        // Note that PDFBox has a bug that visual signing on certified files with permission 2
+        // doesn't work properly, see PDFBOX-3699. As long as this issue is open, you may want to 
+        // be careful with such files.        
+
         PDSignature signature;
 
         // sign a PDF with an existing empty signature, as created by the CreateEmptySignatureForm example. 
@@ -155,6 +164,12 @@ public class CreateVisibleSignature exte
             signature = new PDSignature();
         }
 
+        // Optional: certify 
+        if (accessPermissions == 0)
+        {
+            setMDPPermission(doc, signature, 2);
+        }      
+
         // default filter
         signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
         

Modified: pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java?rev=1786064&r1=1786063&r2=1786064&view=diff
==============================================================================
--- pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java (original)
+++ pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java Wed Mar  8 19:36:43 2017
@@ -192,6 +192,7 @@ public final class COSName extends COSBa
     public static final COSName DOC = new COSName("Doc");
     public static final COSName DOC_CHECKSUM = new COSName("DocChecksum");
     public static final COSName DOC_TIME_STAMP = new COSName("DocTimeStamp");
+    public static final COSName DOCMDP = new COSName("DocMDP");
     public static final COSName DOMAIN = new COSName("Domain");
     public static final COSName DOS = new COSName("DOS");
     public static final COSName DP = new COSName("DP");