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 2021/08/01 14:27:13 UTC

svn commit: r1891949 - in /pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption: PDCryptFilterDictionary.java PublicKeySecurityHandler.java SecurityHandler.java

Author: tilman
Date: Sun Aug  1 14:27:12 2021
New Revision: 1891949

URL: http://svn.apache.org/viewvc?rev=1891949&view=rev
Log:
PDFBOX-5249: fix bug in decryption of AES documents with unencrypted metadata, by Christian Appl

Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PDCryptFilterDictionary.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PublicKeySecurityHandler.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PDCryptFilterDictionary.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PDCryptFilterDictionary.java?rev=1891949&r1=1891948&r2=1891949&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PDCryptFilterDictionary.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PDCryptFilterDictionary.java Sun Aug  1 14:27:12 2021
@@ -17,6 +17,8 @@
 
 package org.apache.pdfbox.pdmodel.encryption;
 
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSBoolean;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.pdmodel.common.COSObjectable;
@@ -107,4 +109,30 @@ public class PDCryptFilterDictionary imp
         return cryptFilterDictionary.getCOSName(COSName.CFM);
     }
 
+    /**
+     * Will get the EncryptMetaData dictionary info.
+     *
+     * @return true if EncryptMetaData is explicitly set (the default is true)
+     */
+    public boolean isEncryptMetaData()
+    {
+        COSBase value = getCOSObject().getDictionaryObject(COSName.ENCRYPT_META_DATA);
+        if (value instanceof COSBoolean)
+        {
+            return ((COSBoolean) value).getValue();
+        }
+
+        // default is true (see 7.6.3.2 Standard Encryption Dictionary PDF 32000-1:2008)
+        return true;
+    }
+
+    /**
+     * Set the EncryptMetaData dictionary info.
+     *
+     * @param encryptMetaData true if EncryptMetaData shall be set.
+     */
+    public void setEncryptMetaData(boolean encryptMetaData)
+    {
+        getCOSObject().setBoolean(COSName.ENCRYPT_META_DATA, encryptMetaData);
+    }
 }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PublicKeySecurityHandler.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PublicKeySecurityHandler.java?rev=1891949&r1=1891948&r2=1891949&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PublicKeySecurityHandler.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PublicKeySecurityHandler.java Sun Aug  1 14:27:12 2021
@@ -68,6 +68,7 @@ import org.bouncycastle.cms.KeyTransReci
 import org.bouncycastle.cms.RecipientId;
 import org.bouncycastle.cms.RecipientInformation;
 import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
+import org.bouncycastle.util.Arrays;
 
 /**
  * This class implements the public key security handler described in the PDF specification.
@@ -126,15 +127,16 @@ public final class PublicKeySecurityHand
                             + "did you pass a null keyStore?");
         }
 
-        setDecryptMetadata(encryption.isEncryptMetaData());
         PDCryptFilterDictionary defaultCryptFilterDictionary = encryption.getDefaultCryptFilterDictionary();
         if (defaultCryptFilterDictionary != null && defaultCryptFilterDictionary.getLength() != 0)
         {
             setKeyLength(defaultCryptFilterDictionary.getLength());
+            setDecryptMetadata(defaultCryptFilterDictionary.isEncryptMetaData());
         }
         else if (encryption.getLength() != 0)
         {
             setKeyLength(encryption.getLength());
+            setDecryptMetadata(encryption.isEncryptMetaData());
         }
 
         PublicKeyDecryptionMaterial material = (PublicKeyDecryptionMaterial) decryptionMaterial;
@@ -244,6 +246,13 @@ public final class PublicKeySecurityHand
             byte[] mdResult;
             if (encryption.getVersion() == 4 || encryption.getVersion() == 5)
             {
+                if (!isDecryptMetadata())
+                {
+                    // "4 bytes with the value 0xFF if the key being generated is intended for use in
+                    // document-level encryption and the document metadata is being left as plaintext"
+                    sha1Input = Arrays.copyOf(sha1Input, sha1Input.length + 4);
+                    System.arraycopy(new byte[]{ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}, 0, sha1Input, sha1Input.length - 4, 4);
+                }
                 if (encryption.getVersion() == 4)
                 {
                     mdResult = MessageDigests.getSHA1().digest(sha1Input);

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java?rev=1891949&r1=1891948&r2=1891949&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java Sun Aug  1 14:27:12 2021
@@ -140,7 +140,17 @@ public abstract class SecurityHandler<T_
     {
         this.decryptMetadata = decryptMetadata;
     }
-    
+
+    /**
+     * Returns true if meta data is to be decrypted.
+     *
+     * @return True if meta data has to be decrypted.
+     */
+    public boolean isDecryptMetadata()
+    {
+        return decryptMetadata;
+    }
+
     /**
      * Set the string filter name.
      *