Author: tilman
Date: Thu Feb 27 05:31:10 2025
New Revision: 1924074

URL: http://svn.apache.org/viewvc?rev=1924074&view=rev
Log:
PDFBOX-5955: pad encryption key as suggested by Ross Johnson; add test

Modified:
    
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java
    
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java

Modified: 
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java
URL: 
http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java?rev=1924074&r1=1924073&r2=1924074&view=diff
==============================================================================
--- 
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java
 (original)
+++ 
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java
 Thu Feb 27 05:31:10 2025
@@ -233,6 +233,9 @@ public final class StandardSecurityHandl
 
         AccessPermission currentAccessPermission;
 
+        byte[] encryptedKey;
+        byte[] passwordBytes;
+        boolean isOwnerPassword;
         if( isOwnerPassword(password.getBytes(passwordCharset), userKey, 
ownerKey,
                                  dicPermissions, documentIDBytes, dicRevision,
                                  dicLength, encryptMetadata) )
@@ -240,26 +243,16 @@ public final class StandardSecurityHandl
             currentAccessPermission = 
AccessPermission.getOwnerAccessPermission();
             setCurrentAccessPermission(currentAccessPermission);
             
-            byte[] computedPassword;
             if (dicRevision == 6 || dicRevision == 5)
             {
-                computedPassword = password.getBytes(passwordCharset);
+                passwordBytes = password.getBytes(passwordCharset);
             }
             else
             {
-                computedPassword = 
getUserPassword(password.getBytes(passwordCharset),
+                passwordBytes = 
getUserPassword(password.getBytes(passwordCharset),
                         ownerKey, dicRevision, dicLength );
             }
-            
-            setEncryptionKey(
-                computeEncryptedKey(
-                    computedPassword,
-                    ownerKey, userKey, oe, ue,
-                    dicPermissions,
-                    documentIDBytes,
-                    dicRevision,
-                    dicLength,
-                    encryptMetadata, true));
+            isOwnerPassword = true;
         }
         else if( isUserPassword(password.getBytes(passwordCharset), userKey, 
ownerKey,
                            dicPermissions, documentIDBytes, dicRevision,
@@ -268,21 +261,27 @@ public final class StandardSecurityHandl
             currentAccessPermission = new AccessPermission(dicPermissions);
             currentAccessPermission.setReadOnly();
             setCurrentAccessPermission(currentAccessPermission);
-            
-            setEncryptionKey(
-                computeEncryptedKey(
-                    password.getBytes(passwordCharset),
-                    ownerKey, userKey, oe, ue,
-                    dicPermissions,
-                    documentIDBytes,
-                    dicRevision,
-                    dicLength,
-                    encryptMetadata, false));
+            passwordBytes = password.getBytes(passwordCharset);
+            isOwnerPassword = false;
         }
         else
         {
             throw new InvalidPasswordException("Cannot decrypt PDF, the 
password is incorrect");
         }
+        encryptedKey = computeEncryptedKey(
+            passwordBytes,
+            ownerKey, userKey, oe, ue,
+            dicPermissions,
+            documentIDBytes,
+            dicRevision,
+            dicLength,
+            encryptMetadata, isOwnerPassword);
+        if (dicRevision == 4 && encryptedKey.length < 16)
+        {
+            LOG.info("PDFBOX-5955: padding RC4 key to length 16");
+            encryptedKey = Arrays.copyOf(encryptedKey, 16);
+        }
+        setEncryptionKey(encryptedKey);
 
         if (dicRevision == 6 || dicRevision == 5)
         {

Modified: 
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java
URL: 
http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java?rev=1924074&r1=1924073&r2=1924074&view=diff
==============================================================================
--- 
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java
 (original)
+++ 
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java
 Thu Feb 27 05:31:10 2025
@@ -46,6 +46,7 @@ import org.apache.pdfbox.pdmodel.encrypt
 import org.apache.pdfbox.pdmodel.encryption.StandardSecurityHandler;
 import org.apache.pdfbox.pdmodel.graphics.image.ValidateXImage;
 import org.apache.pdfbox.rendering.PDFRenderer;
+import org.apache.pdfbox.text.PDFTextStripper;
 import org.apache.pdfbox.util.Charsets;
 import org.junit.Assert;
 
@@ -235,6 +236,38 @@ public class TestSymmetricKeyEncryption
     }
 
     /**
+     * PDFBOX-5955: test unusual RC4 encryption that has 40 or 48 bits instead 
of 128.
+     *
+     * @throws IOException 
+     */
+    public void testPDFBox5955() throws IOException
+    {        
+        File file40bit = new File("target/pdfs", "PDFBOX-5955-40bit.pdf");
+        File file48bit = new File("target/pdfs", "PDFBOX-5955-48bit.pdf");
+        PDDocument doc = PDDocument.load(file40bit);
+        
+        PDFTextStripper stripper = new PDFTextStripper();
+        String text = stripper.getText(doc);
+        assertTrue(text.contains("0x0446615747"));
+        doc.close();
+        doc = PDDocument.load(file40bit);
+        stripper = new PDFTextStripper();
+        text = stripper.getText(doc);
+        assertTrue(text.contains("0x0446615747"));
+        doc.close();
+        doc = PDDocument.load(file48bit);
+        stripper = new PDFTextStripper();
+        text = stripper.getText(doc);
+        assertTrue(text.contains("0x02988E82AFF8"));
+        doc.close();
+        doc = PDDocument.load(file48bit);
+        stripper = new PDFTextStripper();
+        text = stripper.getText(doc);
+        assertTrue(text.contains("0x02988E82AFF8"));
+        doc.close();
+    }
+
+    /**
      * Protect a document with an embedded PDF with a key and try to reopen it
      * with that key and compare.
      *


Reply via email to