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/10/31 18:22:45 UTC
svn commit: r1635818 -
/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java
Author: tilman
Date: Fri Oct 31 17:22:44 2014
New Revision: 1635818
URL: http://svn.apache.org/r1635818
Log:
PDFBOX-2456: add test for encrypt decrypt compare embedded file, as suggested by Ralf Hauser; refactored his code
Modified:
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java
Modified: pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java?rev=1635818&r1=1635817&r2=1635818&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java (original)
+++ pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/encryption/TestSymmetricKeyEncryption.java Fri Oct 31 17:22:44 2014
@@ -20,17 +20,28 @@ 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.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.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.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.DecryptionMaterial;
import org.apache.pdfbox.pdmodel.encryption.StandardDecryptionMaterial;
@@ -46,26 +57,18 @@ import org.junit.Assert;
*/
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;
- private int sizePriorToEncryption = -1;
- private int sizePriorToEncryptionInnerSubfile = -1;
-
static final String PASSWORD = "1234567890abcdefghijk1234567890abcdefghijk";
- static byte[] inputFileAsByteArray = null;
- static byte[] inputInner = null;
-
- static long page0size = -1;
-
- /**
- * Simple test document that gets encrypted by the test cases.
- */
- private PDDocument document;
-
/**
* {@inheritDoc}
*/
@@ -100,79 +103,22 @@ public class TestSymmetricKeyEncryption
permission2.setCanModifyAnnotations(false);
permission2.setCanPrint(true); // it is true now !
permission2.setCanPrintDegraded(false);
-
- String testFileName = "test.pdf";
- inputFileAsByteArray = getFileAsByteArray(testFileName);
- try
- {
- sizePriorToEncryption = inputFileAsByteArray.length;
- document = PDDocument.load(new ByteArrayInputStream(inputFileAsByteArray));
- }
- catch (Exception t)
- {
- System.err.println(testFileName + " " + t.getMessage());
- t.printStackTrace();
- throw t;
- }
- }
-
- public byte[] getFileAsByteArray(String testFileName) throws Exception,
- IOException
- {
- InputStream is = TestSymmetricKeyEncryption.class
- .getResourceAsStream(testFileName);
- try
- {
- try
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- while (true)
- {
- int c = is.read();
- if (c == -1)
- {
- break;
- }
- baos.write(c);
- }
- baos.close();
- return baos.toByteArray();
- }
- finally
- {
- is.close();
- }
- }
- catch (Exception t)
- {
- System.err.println(testFileName + " " + t.getMessage());
- t.printStackTrace();
- throw t;
- }
- finally
- {
- is.close();
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void tearDown() throws Exception
- {
- document.close();
}
/**
- * Protect a document with a public certificate and try to open it with the
- * corresponding private certificate.
+ * 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("test.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);
@@ -180,12 +126,41 @@ public class TestSymmetricKeyEncryption
// 1) check permissions
// 2) 256 key length
//document = PDDocument.load(new ByteArrayInputStream(inputFileAsByteArray));
- //testSymmEncrForKeySize(256, sizePriorToEncryption, document, PASSWORD);
+ //testSymmEncrForKeySize(256, sizePriorToEncryption, document, PASSWORD, permission1);
}
- public void testSymmEncrForKeySize(int keyLength,
- int sizePriorToEncr, PDDocument doc, String password, AccessPermission permission) throws IOException
+ /**
+ * 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);
+
+ //TODO enable when 256 key works
+ //docWithEmbeddedFile = PDDocument.load(new ByteArrayInputStream(inputFileWithEmbeddedFileAsByteArray));
+ //testSymmEncrForKeySizeInner(256, sizeOfFileWithEmbeddedFile, docWithEmbeddedFile, sizeOfEmbeddedFile);
+ }
+
+ private void testSymmEncrForKeySize(int keyLength,
+ int sizePriorToEncr, PDDocument document, String password, AccessPermission permission) throws IOException
+ {
+ String prefix = "Simple-";
int numSrcPages = document.getNumberOfPages();
PDFRenderer pdfRenderer = new PDFRenderer(document);
ArrayList<BufferedImage> srcImgTab = new ArrayList<BufferedImage>();
@@ -201,7 +176,7 @@ public class TestSymmetricKeyEncryption
srcContentStreamTab.add(baos);
}
- PDDocument encryptedDoc = encrypt(keyLength, sizePriorToEncr, doc, "", permission);
+ PDDocument encryptedDoc = encrypt(keyLength, sizePriorToEncr, document, prefix, permission);
try
{
@@ -218,19 +193,19 @@ public class TestSymmetricKeyEncryption
// compare content stream
BufferedImage bim = pdfRenderer.renderImage(i);
ValidateXImage.checkIdent(bim, srcImgTab.get(i));
-
+
// compare content streams
COSStream contentStreamDecr = encryptedDoc.getPage(i).getContentStream();
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());
+ Assert.assertArrayEquals("content stream of page " + i + " not identical",
+ srcContentStreamTab.get(i).toByteArray(),
+ baos.toByteArray());
}
- File pdfFile = new File(testResultsDir, keyLength + "-bit-decrypted.pdf");
+ File pdfFile = new File(testResultsDir, prefix + keyLength + "-bit-decrypted.pdf");
encryptedDoc.save(pdfFile);
boolean canAssembleDocument = newPermission.canAssembleDocument();
@@ -259,7 +234,7 @@ public class TestSymmetricKeyEncryption
}
public PDDocument encrypt(int keyLength, int sizePriorToEncr,
- PDDocument doc, String spec, AccessPermission permission) throws IOException
+ PDDocument doc, String prefix, AccessPermission permission) throws IOException
{
AccessPermission ap = new AccessPermission();
StandardProtectionPolicy spp = new StandardProtectionPolicy(PASSWORD, PASSWORD, ap);
@@ -267,7 +242,7 @@ public class TestSymmetricKeyEncryption
spp.setPermissions(permission);
doc.protect(spp);
- File pdfFile = new File(testResultsDir, keyLength + "-bit-encrypted.pdf");
+ File pdfFile = new File(testResultsDir, prefix + keyLength + "-bit-encrypted.pdf");
doc.save(pdfFile);
doc.close();
@@ -276,9 +251,105 @@ public class TestSymmetricKeyEncryption
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
+ {
+ 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.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));
+ }
}