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 = "";