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 2014/11/05 08:14:09 UTC

svn commit: r1636807 - in /pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox: TestAll.java encryption/TestSymmetricKeyEncryption.java pdmodel/graphics/xobject/PDUtils.java

Author: tilman
Date: Wed Nov  5 07:14:09 2014
New Revision: 1636807

URL: http://svn.apache.org/r1636807
Log:
PDFBOX-2456: activate Symmetric key tests from Ralf Hauser

Added:
    pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java   (with props)
Modified:
    pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/TestAll.java
    pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDUtils.java

Modified: pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/TestAll.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/TestAll.java?rev=1636807&r1=1636806&r2=1636807&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/TestAll.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/TestAll.java Wed Nov  5 07:14:09 2014
@@ -23,6 +23,8 @@ import junit.framework.TestSuite;
 import org.apache.pdfbox.cos.TestCOSFloat;
 import org.apache.pdfbox.cos.TestCOSInteger;
 import org.apache.pdfbox.cos.TestCOSString;
+import org.apache.pdfbox.encryption.TestPublicKeyEncryption;
+import org.apache.pdfbox.encryption.TestSymmetricKeyEncryption;
 import org.apache.pdfbox.filter.TestFilters;
 import org.apache.pdfbox.io.TestIOUtils;
 import org.apache.pdfbox.io.TestRandomAccessBuffer;
@@ -133,6 +135,9 @@ public class TestAll extends TestCase
 
         suite.addTestSuite(EndstreamOutputStreamTest.class);
         suite.addTestSuite(PDFStreamParserTest.class);        
+        
+        suite.addTestSuite(TestPublicKeyEncryption.class);
+        suite.addTestSuite(TestSymmetricKeyEncryption.class);
 
         return suite;
     }

Added: pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java?rev=1636807&view=auto
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java (added)
+++ pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java Wed Nov  5 07:14:09 2014
@@ -0,0 +1,356 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pdfbox.encryption;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import javax.crypto.Cipher;
+
+import junit.framework.TestCase;
+import static junit.framework.TestCase.fail;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.exceptions.COSVisitorException;
+import org.apache.pdfbox.exceptions.CryptographyException;
+import org.apache.pdfbox.io.IOUtils;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
+import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
+import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.common.COSObjectable;
+import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
+import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
+import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
+import org.apache.pdfbox.pdmodel.encryption.BadSecurityHandlerException;
+import org.apache.pdfbox.pdmodel.encryption.DecryptionMaterial;
+import org.apache.pdfbox.pdmodel.encryption.StandardDecryptionMaterial;
+import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy;
+import org.apache.pdfbox.pdmodel.graphics.xobject.PDUtils;
+import org.junit.Assert;
+
+/**
+ * Tests for public key encryption.
+ *
+ * @author Ralf Hauser
+ */
+public class TestSymmetricKeyEncryption extends TestCase
+{
+    /**
+     * Logger instance.
+     */
+    private static final Log LOG = LogFactory.getLog(TestSymmetricKeyEncryption.class);
+
+    private final File testResultsDir = new File("target/test-output/crypto");
+
+    private AccessPermission permission1;
+    private AccessPermission permission2;
+
+    static final String PASSWORD = "1234567890abcdefghijk1234567890abcdefghijk";
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void setUp() throws Exception
+    {
+        testResultsDir.mkdirs();
+
+        if (Cipher.getMaxAllowedKeyLength("AES") != Integer.MAX_VALUE)
+        {
+            // we need strong encryption for these tests
+            fail("JCE unlimited strength jurisdiction policy files are not installed");
+        }
+
+        permission1 = new AccessPermission();
+        permission1.setCanAssembleDocument(false);
+        permission1.setCanExtractContent(false);
+        permission1.setCanExtractForAccessibility(true);
+        permission1.setCanFillInForm(false);
+        permission1.setCanModify(false);
+        permission1.setCanModifyAnnotations(false);
+        permission1.setCanPrint(false);
+        permission1.setCanPrintDegraded(false);
+        permission1.setReadOnly();
+
+        permission2 = new AccessPermission();
+        permission2.setCanAssembleDocument(false);
+        permission2.setCanExtractContent(false);
+        permission2.setCanExtractForAccessibility(true);
+        permission2.setCanFillInForm(false);
+        permission2.setCanModify(false);
+        permission2.setCanModifyAnnotations(false);
+        permission2.setCanPrint(true); // it is true now !
+        permission2.setCanPrintDegraded(false);
+    }
+
+    /**
+     * Protect a document with a key and try to reopen it with that key and
+     * compare.
+     *
+     * @throws Exception If there is an unexpected error during the test.
+     */
+    public void testProtection() throws Exception
+    {
+        byte[] inputFileAsByteArray = getFileResourceAsByteArray("Acroform-PDFBOX-2333.pdf");
+        int sizePriorToEncryption = inputFileAsByteArray.length;
+
+        PDDocument document = PDDocument.load(new ByteArrayInputStream(inputFileAsByteArray));
+        testSymmEncrForKeySize(40, sizePriorToEncryption, document, PASSWORD, permission1);
+
+        document = PDDocument.load(new ByteArrayInputStream(inputFileAsByteArray));
+        testSymmEncrForKeySize(128, sizePriorToEncryption, document, PASSWORD, permission1);
+
+        //TODO check permissions
+    }
+
+    /**
+     * Protect a document with an embedded PDF with a key and try to reopen it
+     * with that key and compare.
+     *
+     * @throws Exception If there is an unexpected error during the test.
+     */
+    public void testProtectionInnerAttachment() throws Exception
+    {
+        String testFileName = "preEnc_20141025_105451.pdf";
+        byte[] inputFileWithEmbeddedFileAsByteArray = getFileResourceAsByteArray(testFileName);
+
+        PDDocument docWithEmbeddedFile;
+        int sizeOfFileWithEmbeddedFile = inputFileWithEmbeddedFileAsByteArray.length;
+
+        File extractedEmbeddedFile
+                = extractEmbeddedFile(new ByteArrayInputStream(inputFileWithEmbeddedFileAsByteArray), "innerFile.pdf");
+
+        docWithEmbeddedFile = PDDocument.load(new ByteArrayInputStream(inputFileWithEmbeddedFileAsByteArray));
+        testSymmEncrForKeySizeInner(40, sizeOfFileWithEmbeddedFile, docWithEmbeddedFile, extractedEmbeddedFile);
+
+        docWithEmbeddedFile = PDDocument.load(new ByteArrayInputStream(inputFileWithEmbeddedFileAsByteArray));
+        testSymmEncrForKeySizeInner(128, sizeOfFileWithEmbeddedFile, docWithEmbeddedFile, extractedEmbeddedFile);
+    }
+
+    private void testSymmEncrForKeySize(int keyLength,
+            int sizePriorToEncr, PDDocument document, String password, AccessPermission permission) throws IOException, BadSecurityHandlerException, CryptographyException, COSVisitorException
+    {
+        String prefix = "Simple-";
+        int numSrcPages = document.getNumberOfPages();
+        ArrayList<BufferedImage> srcImgTab = new ArrayList<BufferedImage>();
+        ArrayList<ByteArrayOutputStream> srcContentStreamTab = new ArrayList<ByteArrayOutputStream>();
+        List<PDPage> pages = document.getDocumentCatalog().getAllPages();
+        for (int i = 0; i < numSrcPages; ++i)
+        {
+            srcImgTab.add(pages.get(i).convertToImage());
+            COSStream contentStream = pages.get(i).getContents().getStream();
+            InputStream unfilteredStream = contentStream.getUnfilteredStream();
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            IOUtils.copy(unfilteredStream, baos);
+            unfilteredStream.close();
+            srcContentStreamTab.add(baos);
+        }
+
+        PDDocument encryptedDoc = encrypt(keyLength, sizePriorToEncr, document, prefix, permission);
+
+        try
+        {
+            Assert.assertTrue(encryptedDoc.isEncrypted());
+            DecryptionMaterial decryptionMaterial = new StandardDecryptionMaterial(PASSWORD);
+            encryptedDoc.openProtection(decryptionMaterial);
+
+            AccessPermission newPermission = encryptedDoc.getCurrentAccessPermission();
+
+            Assert.assertEquals(numSrcPages, encryptedDoc.getNumberOfPages());
+            pages = encryptedDoc.getDocumentCatalog().getAllPages();
+            for (int i = 0; i < encryptedDoc.getNumberOfPages(); ++i)
+            {
+                // compare content stream
+                
+                BufferedImage bim = pages.get(i).convertToImage();
+                PDUtils.checkIdent(bim, srcImgTab.get(i));
+
+                // compare content streams
+                COSStream contentStreamDecr = pages.get(i).getContents().getStream();
+                InputStream unfilteredStream = contentStreamDecr.getUnfilteredStream();
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                IOUtils.copy(unfilteredStream, baos);
+                unfilteredStream.close();
+                Assert.assertArrayEquals("content stream of page " + i + " not identical",
+                        srcContentStreamTab.get(i).toByteArray(),
+                        baos.toByteArray());
+            }
+            
+            encryptedDoc.setAllSecurityToBeRemoved(true);
+
+            File pdfFile = new File(testResultsDir, prefix + keyLength + "-bit-decrypted.pdf");
+            encryptedDoc.save(pdfFile);
+
+            boolean canAssembleDocument = newPermission.canAssembleDocument();
+            boolean canExtractContent = newPermission.canExtractContent();
+            boolean canExtractForAccessibility = newPermission
+                    .canExtractForAccessibility();
+            boolean canFillInForm = newPermission.canFillInForm();
+            boolean canModify = newPermission.canModify();
+            boolean canModifyAnnotations = newPermission.canModifyAnnotations();
+            boolean canPrint = newPermission.canPrint();
+            boolean canPrintDegraded = newPermission.canPrintDegraded();
+            encryptedDoc.close();
+//            Assert.assertFalse(canAssembleDocument);
+//            Assert.assertFalse(canExtractContent);
+//            Assert.assertTrue(canExtractForAccessibility);
+//            Assert.assertFalse(canFillInForm);
+//            Assert.assertFalse(canModify);
+//            Assert.assertFalse(canModifyAnnotations);
+//            Assert.assertFalse(canPrint);
+//            Assert.assertFalse(canPrintDegraded);
+        }
+        finally
+        {
+            encryptedDoc.close();
+        }
+    }
+
+    public PDDocument encrypt(int keyLength, int sizePriorToEncr,
+            PDDocument doc, String prefix, AccessPermission permission) throws IOException, BadSecurityHandlerException, COSVisitorException
+    {
+        AccessPermission ap = new AccessPermission();
+        StandardProtectionPolicy spp = new StandardProtectionPolicy(PASSWORD, PASSWORD, ap);
+        spp.setEncryptionKeyLength(keyLength);
+        spp.setPermissions(permission);
+        doc.protect(spp);
+
+        File pdfFile = new File(testResultsDir, prefix + keyLength + "-bit-encrypted.pdf");
+
+        doc.save(pdfFile);
+        doc.close();
+        long sizeEncrypted = pdfFile.length();
+        PDDocument encryptedDoc = PDDocument.load(pdfFile);
+        Assert.assertTrue(keyLength
+                + "-bit encrypted pdf should not have same size as plain one",
+                sizeEncrypted != sizePriorToEncr);
+        return encryptedDoc;
+    }
+
+    // extract the embedded file, saves it, and return the extracted saved file
+    private File extractEmbeddedFile(InputStream pdfInputStream, String name) throws IOException
+    {
+        PDDocument docWithEmbeddedFile;
+        docWithEmbeddedFile = PDDocument.load(pdfInputStream);
+        PDDocumentCatalog catalog = docWithEmbeddedFile.getDocumentCatalog();
+        PDDocumentNameDictionary names = catalog.getNames();
+        PDEmbeddedFilesNameTreeNode embeddedFiles = names.getEmbeddedFiles();
+        Map<String, COSObjectable> embeddedFileNames = embeddedFiles.getNames();
+        Assert.assertEquals(1, embeddedFileNames.size());
+        Map.Entry<String, COSObjectable> entry = embeddedFileNames.entrySet().iterator().next();
+        LOG.info("Processing embedded file " + entry.getKey() + ":");
+        PDComplexFileSpecification complexFileSpec = (PDComplexFileSpecification) entry.getValue();
+        PDEmbeddedFile embeddedFile = complexFileSpec.getEmbeddedFile();
+
+        File resultFile = new File(testResultsDir, name);
+        FileOutputStream fos = new FileOutputStream(resultFile);
+        InputStream is = embeddedFile.createInputStream();
+        IOUtils.copy(is, fos);
+        fos.close();
+        is.close();
+
+        LOG.info("  size: " + embeddedFile.getSize());
+        assertEquals(embeddedFile.getSize(), resultFile.length());
+
+        return resultFile;
+    }
+
+    private void testSymmEncrForKeySizeInner(int keyLength,
+            int sizePriorToEncr, PDDocument doc,
+            File embeddedFilePriorToEncryption) throws IOException, BadSecurityHandlerException, CryptographyException, COSVisitorException
+    {
+        PDDocument encryptedDoc = encrypt(keyLength, sizePriorToEncr, doc, "ContainsEmbedded-", permission1);
+
+        try
+        {
+            Assert.assertTrue(encryptedDoc.isEncrypted());
+            DecryptionMaterial decryptionMaterial = new StandardDecryptionMaterial(PASSWORD);
+            encryptedDoc.openProtection(decryptionMaterial);
+
+            AccessPermission permission = encryptedDoc.getCurrentAccessPermission();
+
+            File decryptedFile = new File(testResultsDir, "DecryptedContainsEmbedded-" + keyLength + "-bit.pdf");
+            
+            encryptedDoc.setAllSecurityToBeRemoved(true);
+            encryptedDoc.save(decryptedFile);
+
+            File extractedEmbeddedFile = extractEmbeddedFile(new FileInputStream(decryptedFile), "decryptedInnerFile-" + keyLength + "-bit.pdf");
+
+            Assert.assertEquals(keyLength + "-bit decrypted inner attachment pdf should have same size as plain one",
+                    embeddedFilePriorToEncryption.length(), extractedEmbeddedFile.length());
+
+            // compare the two embedded files
+            Assert.assertArrayEquals(
+                    getFileAsByteArray(embeddedFilePriorToEncryption),
+                    getFileAsByteArray(extractedEmbeddedFile));
+
+            boolean canAssembleDocument = permission.canAssembleDocument();
+            boolean canExtractContent = permission.canExtractContent();
+            boolean canExtractForAccessibility = permission
+                    .canExtractForAccessibility();
+            boolean canFillInForm = permission.canFillInForm();
+            boolean canModify = permission.canModify();
+            boolean canModifyAnnotations = permission.canModifyAnnotations();
+            boolean canPrint = permission.canPrint();
+            boolean canPrintDegraded = permission.canPrintDegraded();
+            encryptedDoc.close();
+            // Assert.assertFalse(canAssembleDocument);
+            // Assert.assertFalse(canExtractContent);
+            // Assert.assertTrue(canExtractForAccessibility);
+            // Assert.assertFalse(canFillInForm);
+            // Assert.assertFalse(canModify);
+            // Assert.assertFalse(canModifyAnnotations);
+            // Assert.assertFalse(canPrint);
+            // Assert.assertFalse(canPrintDegraded);
+        }
+        finally
+        {
+            encryptedDoc.close();
+        }
+    }
+
+    private byte[] getStreamAsByteArray(InputStream is) throws IOException
+    {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        IOUtils.copy(is, baos);
+        is.close();
+        return baos.toByteArray();
+    }
+
+    private byte[] getFileResourceAsByteArray(String testFileName) throws IOException
+    {
+        return getStreamAsByteArray(TestSymmetricKeyEncryption.class.getResourceAsStream(testFileName));
+    }
+
+    private byte[] getFileAsByteArray(File f) throws IOException
+    {
+        return getStreamAsByteArray(new FileInputStream(f));
+    }
+
+}

Propchange: pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDUtils.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDUtils.java?rev=1636807&r1=1636806&r2=1636807&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDUtils.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDUtils.java Wed Nov  5 07:14:09 2014
@@ -58,7 +58,7 @@ public class PDUtils
      * @param expectedImage
      * @param actualImage
      */
-    static void checkIdent(BufferedImage expectedImage, BufferedImage actualImage)
+    static public void checkIdent(BufferedImage expectedImage, BufferedImage actualImage)
     {
         String errMsg = "";