You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2020/05/23 10:09:04 UTC
svn commit: r1878049 - in /pdfbox/trunk:
examples/src/test/java/org/apache/pdfbox/examples/pdmodel/
examples/src/test/resources/org/apache/pdfbox/examples/signature/
pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/
Author: lehmi
Date: Sat May 23 10:09:04 2020
New Revision: 1878049
URL: http://svn.apache.org/viewvc?rev=1878049&view=rev
Log:
PDFBOX-4784, closes #83: add optional usage of an external SecureRandom for AES encryption as proposed by Aleksandr Beliakov
Added:
pdfbox/trunk/examples/src/test/resources/org/apache/pdfbox/examples/signature/sign_me_protected.pdf (with props)
Modified:
pdfbox/trunk/examples/src/test/java/org/apache/pdfbox/examples/pdmodel/TestCreateSignature.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.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=1878049&r1=1878048&r2=1878049&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 23 10:09:04 2020
@@ -32,12 +32,15 @@ import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.text.MessageFormat;
import java.util.Arrays;
+import java.util.Calendar;
import java.util.Collection;
+import java.util.Date;
import java.util.List;
import org.apache.pdfbox.Loader;
@@ -53,6 +56,7 @@ import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.encryption.SecurityProvider;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
+import org.apache.pdfbox.pdmodel.interactive.digitalsignature.ExternalSigningSupport;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
import org.apache.pdfbox.rendering.PDFRenderer;
@@ -69,6 +73,7 @@ import org.bouncycastle.cms.CMSSignedDat
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationVerifier;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
+import org.bouncycastle.crypto.prng.FixedSecureRandom;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.tsp.TSPException;
import org.bouncycastle.tsp.TSPValidationException;
@@ -556,4 +561,67 @@ public class TestCreateSignature
Assert.assertArrayEquals(expectedData.getData(), actualData.getData());
}
}
+
+ @Test
+ public void testPDFBox4784() throws Exception
+ {
+
+ Date signingTime = new Date();
+
+ byte[] defaultSignedOne = signEncrypted(null, signingTime);
+ byte[] defaultSignedTwo = signEncrypted(null, signingTime);
+ Assert.assertFalse(Arrays.equals(defaultSignedOne, defaultSignedTwo));
+
+ // a dummy value for FixedSecureRandom is used (for real use-cases a secure value should be provided)
+ byte[] fixedRandomSignedOne = signEncrypted(new FixedSecureRandom(new byte[128]),
+ signingTime);
+ byte[] fixedRandomSignedTwo = signEncrypted(new FixedSecureRandom(new byte[128]),
+ signingTime);
+ Assert.assertTrue(Arrays.equals(fixedRandomSignedOne, fixedRandomSignedTwo));
+
+ }
+
+ private byte[] signEncrypted(SecureRandom secureRandom, Date signingTime) throws Exception
+ {
+ KeyStore keystore = KeyStore.getInstance("PKCS12");
+ keystore.load(new FileInputStream(KEYSTORE_PATH), PASSWORD.toCharArray());
+
+ CreateSignature signing = new CreateSignature(keystore, PASSWORD.toCharArray());
+ signing.setExternalSigning(true);
+
+ File inFile = new File(IN_DIR + "sign_me_protected.pdf");
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ PDDocument doc = null;
+ try
+ {
+ doc = Loader.loadPDF(inFile, " ");
+
+ if (secureRandom != null)
+ {
+ doc.getEncryption().getSecurityHandler().setCustomSecureRandom(secureRandom);
+ }
+
+ PDSignature signature = new PDSignature();
+ signature.setName("Example User");
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(signingTime);
+ signature.setSignDate(cal);
+
+ doc.addSignature(signature);
+ doc.setDocumentId(12345l);
+ ExternalSigningSupport externalSigning = doc.saveIncrementalForExternalSigning(baos);
+ // invoke external signature service
+ byte[] cmsSignature = signing.sign(externalSigning.getContent());
+ // set signature bytes received from the service
+ externalSigning.setSignature(cmsSignature);
+
+ return baos.toByteArray();
+ }
+ finally
+ {
+ IOUtils.closeQuietly(doc);
+ IOUtils.closeQuietly(baos);
+ }
+ }
}
Added: pdfbox/trunk/examples/src/test/resources/org/apache/pdfbox/examples/signature/sign_me_protected.pdf
URL: http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/test/resources/org/apache/pdfbox/examples/signature/sign_me_protected.pdf?rev=1878049&view=auto
==============================================================================
Binary file - no diff available.
Propchange: pdfbox/trunk/examples/src/test/resources/org/apache/pdfbox/examples/signature/sign_me_protected.pdf
------------------------------------------------------------------------------
svn:mime-type = application/pdf
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java?rev=1878049&r1=1878048&r2=1878049&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java Sat May 23 10:09:04 2020
@@ -78,6 +78,9 @@ public abstract class SecurityHandler
/** indicates if the Metadata have to be decrypted of not. */
private boolean decryptMetadata;
+ /** Can be used to allow stateless AES encryption */
+ private SecureRandom customSecureRandom;
+
// PDFBOX-4453, PDFBOX-4477: Originally this was just a Set. This failed in rare cases
// when a decrypted string was identical to an encrypted string.
// Because COSString.equals() checks the contents, decryption was then skipped.
@@ -134,6 +137,16 @@ public abstract class SecurityHandler
}
/**
+ * Set the custom SecureRandom.
+ *
+ * @param secureRandom the custom SecureRandom for AES encryption
+ */
+ public void setCustomSecureRandom(SecureRandom customSecureRandom)
+ {
+ this.customSecureRandom = customSecureRandom;
+ }
+
+ /**
* Prepare the document for encryption.
*
* @param doc The document that will be encrypted.
@@ -372,7 +385,7 @@ public abstract class SecurityHandler
else
{
// generate random IV and write to stream
- SecureRandom rnd = new SecureRandom();
+ SecureRandom rnd = getSecureRandom();
rnd.nextBytes(iv);
output.write(iv);
}
@@ -380,9 +393,23 @@ public abstract class SecurityHandler
}
/**
+ * Returns a SecureRandom If customSecureRandom is not defined, instantiate a new SecureRandom
+ *
+ * @return SecureRandom
+ */
+ private SecureRandom getSecureRandom()
+ {
+ if (customSecureRandom != null)
+ {
+ return customSecureRandom;
+ }
+ return new SecureRandom();
+ }
+
+ /**
* This will dispatch to the correct method.
*
- * @param obj The object to decrypt.
+ * @param obj The object to decrypt.
* @param objNum The object number.
* @param genNum The object generation Number.
*