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 2017/05/27 15:33:18 UTC
svn commit: r1796417 - in /pdfbox/trunk:
examples/src/test/java/org/apache/pdfbox/examples/pdmodel/TestCreateSignature.java
pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java
Author: tilman
Date: Sat May 27 15:33:18 2017
New Revision: 1796417
URL: http://svn.apache.org/viewvc?rev=1796417&view=rev
Log:
PDFBOX-3811: add exception if saveIncrementalForExternalSigning is called twice without initializing reserve byte range, and a test inspired by Le Duc Duy
Modified:
pdfbox/trunk/examples/src/test/java/org/apache/pdfbox/examples/pdmodel/TestCreateSignature.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java
Modified: pdfbox/trunk/examples/src/test/java/org/apache/pdfbox/examples/pdmodel/TestCreateSignature.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/test/java/org/apache/pdfbox/examples/pdmodel/TestCreateSignature.java?rev=1796417&r1=1796416&r2=1796417&view=diff
==============================================================================
--- pdfbox/trunk/examples/src/test/java/org/apache/pdfbox/examples/pdmodel/TestCreateSignature.java (original)
+++ pdfbox/trunk/examples/src/test/java/org/apache/pdfbox/examples/pdmodel/TestCreateSignature.java Sat May 27 15:33:18 2017
@@ -16,6 +16,7 @@
*/
package org.apache.pdfbox.examples.pdmodel;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -24,20 +25,24 @@ import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import javax.xml.bind.DatatypeConverter;
+
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSString;
-
import org.apache.pdfbox.examples.signature.CreateSignature;
import org.apache.pdfbox.examples.signature.CreateVisibleSignature;
import org.apache.pdfbox.examples.signature.TSAClient;
import org.apache.pdfbox.io.IOUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import org.apache.wink.client.MockHttpServer;
import org.bouncycastle.cert.X509CertificateHolder;
@@ -256,4 +261,58 @@ public class TestCreateSignature
}
}
}
+
+ private String calculateDigestString(InputStream inputStream) throws NoSuchAlgorithmException, IOException
+ {
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
+ return DatatypeConverter.printHexBinary(md.digest(IOUtils.toByteArray(inputStream)));
+ }
+
+ /**
+ * PDFBOX-3811: make sure that calling saveIncrementalForExternalSigning() more than once
+ * brings the same result.
+ *
+ * @throws IOException
+ * @throws NoSuchAlgorithmException
+ */
+ @Test
+ public void testPDFBox3811() throws IOException, NoSuchAlgorithmException
+ {
+ if (!externallySign)
+ {
+ return;
+ }
+
+ // create simple PDF
+ PDDocument document = new PDDocument();
+ PDPage page = new PDPage();
+ document.addPage(page);
+ new PDPageContentStream(document, page).close();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ document.save(baos);
+ document.close();
+
+ document = PDDocument.load(baos.toByteArray());
+ // for stable digest
+ document.setDocumentId(12345L);
+
+ PDSignature signature = new PDSignature();
+ signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
+ signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
+ document.addSignature(signature);
+
+ String digestString = calculateDigestString(document.saveIncrementalForExternalSigning(new ByteArrayOutputStream()).getContent());
+ boolean caught = false;
+ try
+ {
+ document.saveIncrementalForExternalSigning(new ByteArrayOutputStream());
+ }
+ catch (IllegalStateException ex)
+ {
+ caught = true;
+ }
+ Assert.assertTrue("IllegalStateException should have been thrown", caught);
+ document.getLastSignatureDictionary().setByteRange(PDDocument.RESERVE_BYTE_RANGE);
+ Assert.assertEquals(digestString, calculateDigestString(document.saveIncrementalForExternalSigning(new ByteArrayOutputStream()).getContent()));
+ }
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java?rev=1796417&r1=1796416&r2=1796417&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java Sat May 27 15:33:18 2017
@@ -24,6 +24,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -77,6 +78,13 @@ import org.apache.pdfbox.pdmodel.interac
*/
public class PDDocument implements Closeable
{
+ /**
+ * For signing: large reserve byte range used as placeholder in the saved PDF until actual the
+ * length of the PDF is known. You'll need to assign this yourself (with {@link PDSignature#setByteRange(int[])} ) only if you call
+ * {@link #saveIncrementalForExternalSigning(java.io.OutputStream) saveIncrementalForExternalSigning()} twice.
+ */
+ public static final int[] RESERVE_BYTE_RANGE = new int[] { 0, 1000000000, 1000000000, 1000000000 };
+
private static final Log LOG = LogFactory.getLog(PDDocument.class);
/**
@@ -263,8 +271,8 @@ public class PDDocument implements Close
sigObject.setContents(new byte[SignatureOptions.DEFAULT_SIGNATURE_SIZE]);
}
- // Reserve ByteRange
- sigObject.setByteRange(new int[] { 0, 1000000000, 1000000000, 1000000000 });
+ // Reserve ByteRange, will be overwritten in COSWriter
+ sigObject.setByteRange(RESERVE_BYTE_RANGE);
signInterface = signatureInterface;
@@ -1336,6 +1344,12 @@ public class PDDocument implements Close
{
throw new IllegalStateException("document was not loaded from a file or a stream");
}
+ int[] byteRange = getLastSignatureDictionary().getByteRange();
+ if (!Arrays.equals(byteRange, RESERVE_BYTE_RANGE))
+ {
+ throw new IllegalStateException("signature reserve byte range has been changed "
+ + "after addSignature(), please call setByteRange(RESERVE_BYTE_RANGE)");
+ }
COSWriter writer = new COSWriter(output, pdfSource);
writer.write(this);
signingSupport = new SigningSupport(writer);