diff --git a/itext.tests/itext.sign.tests/itext/signatures/PdfTwoPhaseSignerUnitTest.cs b/itext.tests/itext.sign.tests/itext/signatures/PdfTwoPhaseSignerUnitTest.cs
index e203733b68..066eb4c97c 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/PdfTwoPhaseSignerUnitTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/PdfTwoPhaseSignerUnitTest.cs
@@ -96,21 +96,48 @@ public virtual void AddSignatureToPreparedDocumentTest() {
PdfTwoPhaseSigner signer = new PdfTwoPhaseSigner(reader, outputStream);
int estimatedSize = 8079;
SignerProperties signerProperties = new SignerProperties();
- byte[] digest = signer.PrepareDocumentForSignature(signerProperties, DigestAlgorithms.SHA256, PdfName.Adobe_PPKLite
- , PdfName.Adbe_pkcs7_detached, estimatedSize, false);
+ signer.PrepareDocumentForSignature(signerProperties, DigestAlgorithms.SHA256, PdfName.Adobe_PPKLite, PdfName
+ .Adbe_pkcs7_detached, estimatedSize, false);
String fieldName = signerProperties.GetFieldName();
- PdfReader resultReader = new PdfReader(new MemoryStream(outputStream.ToArray()));
- PdfDocument resultDoc = new PdfDocument(resultReader);
- ByteArrayOutputStream completedOutputStream = new ByteArrayOutputStream();
- byte[] testData = ByteUtils.GetIsoBytes("Some data to test the signature addition with");
- PdfTwoPhaseSigner.AddSignatureToPreparedDocument(resultDoc, fieldName, completedOutputStream, testData);
- resultReader = new PdfReader(new MemoryStream(completedOutputStream.ToArray()));
- resultDoc = new PdfDocument(resultReader);
- SignatureUtil signatureUtil = new SignatureUtil(resultDoc);
- PdfSignature signature = signatureUtil.GetSignature(fieldName);
- byte[] content = signature.GetContents().GetValueBytes();
- for (int i = 0; i < testData.Length; i++) {
- NUnit.Framework.Assert.AreEqual(testData[i], content[i]);
+ using (PdfReader resultReader = new PdfReader(new MemoryStream(outputStream.ToArray()))) {
+ ByteArrayOutputStream completedOutputStream = new ByteArrayOutputStream();
+ byte[] testData = ByteUtils.GetIsoBytes("Some data to test the signature addition with");
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(resultReader, fieldName, completedOutputStream, testData);
+ using (PdfDocument resultDoc = new PdfDocument(new PdfReader(new MemoryStream(completedOutputStream.ToArray
+ ())))) {
+ SignatureUtil signatureUtil = new SignatureUtil(resultDoc);
+ PdfSignature signature = signatureUtil.GetSignature(fieldName);
+ byte[] content = signature.GetContents().GetValueBytes();
+ for (int i = 0; i < testData.Length; i++) {
+ NUnit.Framework.Assert.AreEqual(testData[i], content[i]);
+ }
+ }
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void AddSignatureToPreparedDocumentDeprecatedApiTest() {
+ PdfReader reader = new PdfReader(new MemoryStream(CreateSimpleDocument()));
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ PdfTwoPhaseSigner signer = new PdfTwoPhaseSigner(reader, outputStream);
+ int estimatedSize = 8079;
+ SignerProperties signerProperties = new SignerProperties();
+ signer.PrepareDocumentForSignature(signerProperties, DigestAlgorithms.SHA256, PdfName.Adobe_PPKLite, PdfName
+ .Adbe_pkcs7_detached, estimatedSize, false);
+ String fieldName = signerProperties.GetFieldName();
+ using (PdfDocument document = new PdfDocument(new PdfReader(new MemoryStream(outputStream.ToArray())))) {
+ ByteArrayOutputStream completedOutputStream = new ByteArrayOutputStream();
+ byte[] testData = ByteUtils.GetIsoBytes("Some data to test the signature addition with");
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(document, fieldName, completedOutputStream, testData);
+ using (PdfDocument resultDoc = new PdfDocument(new PdfReader(new MemoryStream(completedOutputStream.ToArray
+ ())))) {
+ SignatureUtil signatureUtil = new SignatureUtil(resultDoc);
+ PdfSignature signature = signatureUtil.GetSignature(fieldName);
+ byte[] content = signature.GetContents().GetValueBytes();
+ for (int i = 0; i < testData.Length; i++) {
+ NUnit.Framework.Assert.AreEqual(testData[i], content[i]);
+ }
+ }
}
}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/mac/SignedDocumentWithMacTest.cs b/itext.tests/itext.sign.tests/itext/signatures/mac/SignedDocumentWithMacTest.cs
index 94c695cf3a..098532da03 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/mac/SignedDocumentWithMacTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/mac/SignedDocumentWithMacTest.cs
@@ -30,7 +30,6 @@ You should have received a copy of the GNU Affero General Public License
using iText.Commons.Bouncycastle.Crypto;
using iText.Commons.Utils;
using iText.Kernel.Crypto;
-using iText.Kernel.Exceptions;
using iText.Kernel.Logs;
using iText.Kernel.Pdf;
using iText.Signatures;
@@ -82,20 +81,12 @@ public virtual void SignMacProtectedDocTest(String certName, String signingOpera
))) {
using (Stream outputStream = FileUtil.GetFileOutputStream(outputFileName)) {
PdfSigner pdfSigner = new PdfSigner(reader, outputStream, new StampingProperties());
- if (signingOperation.Equals("signExternalContainerBlank")) {
- NUnit.Framework.Assert.Catch(typeof(PdfException), () => PerformSigningOperation(signingOperation, pdfSigner
- , signRsaPrivateKey, signRsaChain));
- }
- else {
- PerformSigningOperation(signingOperation, pdfSigner, signRsaPrivateKey, signRsaChain);
- }
+ PerformSigningOperation(signingOperation, pdfSigner, signRsaPrivateKey, signRsaChain);
}
}
- if (!signingOperation.Equals("signExternalContainerBlank")) {
- ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
- NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
- , properties));
- }
+ ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
+ NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
+ , properties));
}
[NUnit.Framework.TestCaseSource("CreateParameters")]
@@ -112,20 +103,12 @@ public virtual void SignNotMacProtectedDocTest(String certName, String signingOp
))) {
using (Stream outputStream = FileUtil.GetFileOutputStream(outputFileName)) {
PdfSigner pdfSigner = new PdfSigner(reader, outputStream, new StampingProperties());
- if (signingOperation.Equals("signExternalContainerBlank")) {
- NUnit.Framework.Assert.Catch(typeof(PdfException), () => PerformSigningOperation(signingOperation, pdfSigner
- , signRsaPrivateKey, signRsaChain));
- }
- else {
- PerformSigningOperation(signingOperation, pdfSigner, signRsaPrivateKey, signRsaChain);
- }
+ PerformSigningOperation(signingOperation, pdfSigner, signRsaPrivateKey, signRsaChain);
}
}
- if (!signingOperation.Equals("signExternalContainerBlank")) {
- ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
- NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
- , properties));
- }
+ ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
+ NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
+ , properties));
}
[NUnit.Framework.TestCaseSource("CreateParameters")]
@@ -145,7 +128,6 @@ public virtual void SignNotMacProtectedDoc17Test(String certName, String signing
PerformSigningOperation(signingOperation, pdfSigner, signRsaPrivateKey, signRsaChain);
}
}
- // TODO DEVSIX-8637 Add else statement for empty signature container
if (!signingOperation.Equals("signExternalContainerBlank")) {
ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
@@ -171,7 +153,6 @@ public virtual void SignNotMacProtectedDocInAppendModeTest(String certName, Stri
PerformSigningOperation(signingOperation, pdfSigner, signRsaPrivateKey, signRsaChain);
}
}
- // TODO DEVSIX-8637 Add else statement for empty signature container
if (!signingOperation.Equals("signExternalContainerBlank")) {
ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
@@ -193,20 +174,12 @@ public virtual void SignMacProtectedDocInAppendModeTest(String certName, String
))) {
using (Stream outputStream = FileUtil.GetFileOutputStream(outputFileName)) {
PdfSigner pdfSigner = new PdfSigner(reader, outputStream, new StampingProperties().UseAppendMode());
- if (signingOperation.Equals("signExternalContainerBlank")) {
- NUnit.Framework.Assert.Catch(typeof(PdfException), () => PerformSigningOperation(signingOperation, pdfSigner
- , signRsaPrivateKey, signRsaChain));
- }
- else {
- PerformSigningOperation(signingOperation, pdfSigner, signRsaPrivateKey, signRsaChain);
- }
+ PerformSigningOperation(signingOperation, pdfSigner, signRsaPrivateKey, signRsaChain);
}
}
- if (!signingOperation.Equals("signExternalContainerBlank")) {
- ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
- NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
- , properties));
- }
+ ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
+ NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
+ , properties));
}
[NUnit.Framework.TestCaseSource("CreateParameters")]
@@ -223,20 +196,12 @@ public virtual void SignMacProtectedDocWithSHA3_384Test(String certName, String
))) {
using (Stream outputStream = FileUtil.GetFileOutputStream(outputFileName)) {
PdfSigner pdfSigner = new PdfSigner(reader, outputStream, new StampingProperties());
- if (signingOperation.Equals("signExternalContainerBlank")) {
- NUnit.Framework.Assert.Catch(typeof(PdfException), () => PerformSigningOperation(signingOperation, pdfSigner
- , signRsaPrivateKey, signRsaChain));
- }
- else {
- PerformSigningOperation(signingOperation, pdfSigner, signRsaPrivateKey, signRsaChain);
- }
+ PerformSigningOperation(signingOperation, pdfSigner, signRsaPrivateKey, signRsaChain);
}
}
- if (!signingOperation.Equals("signExternalContainerBlank")) {
- ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
- NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
- , properties));
- }
+ ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
+ NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
+ , properties));
}
[NUnit.Framework.TestCaseSource("CreateParameters")]
@@ -262,19 +227,11 @@ public virtual void SignMacPublicEncryptionDocTest(String certName, String signi
using (PdfReader reader = new PdfReader(srcFileName, properties)) {
using (Stream outputStream = FileUtil.GetFileOutputStream(outputFileName)) {
PdfSigner pdfSigner = new PdfSigner(reader, outputStream, new StampingProperties());
- if (signingOperation.Equals("signExternalContainerBlank")) {
- NUnit.Framework.Assert.Catch(typeof(PdfException), () => PerformSigningOperation(signingOperation, pdfSigner
- , signRsaPrivateKey, signRsaChain));
- }
- else {
- PerformSigningOperation(signingOperation, pdfSigner, signRsaPrivateKey, signRsaChain);
- }
+ PerformSigningOperation(signingOperation, pdfSigner, signRsaPrivateKey, signRsaChain);
}
}
- if (!signingOperation.Equals("signExternalContainerBlank")) {
- NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
- , properties));
- }
+ NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
+ , properties));
}
private static void PerformSigningOperation(String signingOperation, PdfSigner pdfSigner, IPrivateKey privateKey
diff --git a/itext.tests/itext.sign.tests/itext/signatures/mac/TwoStepSigningWithMacTest.cs b/itext.tests/itext.sign.tests/itext/signatures/mac/TwoStepSigningWithMacTest.cs
new file mode 100644
index 0000000000..5e5a5ff8e4
--- /dev/null
+++ b/itext.tests/itext.sign.tests/itext/signatures/mac/TwoStepSigningWithMacTest.cs
@@ -0,0 +1,184 @@
+/*
+This file is part of the iText (R) project.
+Copyright (c) 1998-2024 Apryse Group NV
+Authors: Apryse Software.
+
+This program is offered under a commercial and under the AGPL license.
+For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
+
+AGPL licensing:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+using System;
+using System.IO;
+using iText.Bouncycastleconnector;
+using iText.Commons.Bouncycastle;
+using iText.Commons.Bouncycastle.Cert;
+using iText.Commons.Bouncycastle.Crypto;
+using iText.Commons.Utils;
+using iText.Kernel.Pdf;
+using iText.Signatures;
+using iText.Signatures.Testutils;
+using iText.Test;
+
+namespace iText.Signatures.Mac {
+ [NUnit.Framework.Category("BouncyCastleIntegrationTest")]
+ public class TwoStepSigningWithMacTest : ExtendedITextTest {
+ private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory();
+
+ private static readonly String CERTS_SRC = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
+ .CurrentContext.TestDirectory) + "/resources/itext/signatures/certs/";
+
+ private static readonly String SOURCE_FOLDER = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
+ .CurrentContext.TestDirectory) + "/resources/itext/signatures/mac/TwoStepSigningWithMacTest/";
+
+ private static readonly String DESTINATION_FOLDER = NUnit.Framework.TestContext.CurrentContext.TestDirectory
+ + "/test/itext/signatures/mac/TwoStepSigningWithMacTest/";
+
+ private static readonly byte[] ENCRYPTION_PASSWORD = "123".GetBytes();
+
+ private static readonly char[] PRIVATE_KEY_PASSWORD = "testpassphrase".ToCharArray();
+
+ [NUnit.Framework.OneTimeSetUp]
+ public static void Before() {
+ CreateOrClearDestinationFolder(DESTINATION_FOLDER);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void SignDeferredWithReaderTest() {
+ String fileName = "signDeferredWithReaderTest.pdf";
+ String srcFileName = SOURCE_FOLDER + "macEncryptedDoc.pdf";
+ String outputFileName = DESTINATION_FOLDER + fileName;
+ String signCertFileName = CERTS_SRC + "signCertRsa01.pem";
+ String cmpFileName = SOURCE_FOLDER + "cmp_" + fileName;
+ IX509Certificate[] signRsaChain = PemFileHelper.ReadFirstChain(signCertFileName);
+ IPrivateKey signRsaPrivateKey = PemFileHelper.ReadFirstKey(signCertFileName, PRIVATE_KEY_PASSWORD);
+ ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
+ MemoryStream preparedDocument = new MemoryStream();
+ using (PdfReader reader = new PdfReader(srcFileName, properties)) {
+ using (Stream outputStream = preparedDocument) {
+ PdfSigner pdfSigner = new PdfSigner(reader, outputStream, new StampingProperties());
+ pdfSigner.SignExternalContainer(new ExternalBlankSignatureContainer(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached
+ ), 5000);
+ }
+ }
+ using (PdfReader reader_1 = new PdfReader(new MemoryStream(preparedDocument.ToArray()), properties)) {
+ using (Stream outputStream_1 = FileUtil.GetFileOutputStream(outputFileName)) {
+ PdfSigner.SignDeferred(reader_1, "Signature1", outputStream_1, new PKCS7ExternalSignatureContainer(signRsaPrivateKey
+ , signRsaChain, "SHA-512"));
+ }
+ }
+ NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
+ , properties));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void SignDeferredWithDocumentTest() {
+ String fileName = "signDeferredWithDocumentTest.pdf";
+ String srcFileName = SOURCE_FOLDER + "macEncryptedDoc.pdf";
+ String outputFileName = DESTINATION_FOLDER + fileName;
+ String signCertFileName = CERTS_SRC + "signCertRsa01.pem";
+ String cmpFileName = SOURCE_FOLDER + "cmp_" + fileName;
+ IX509Certificate[] signRsaChain = PemFileHelper.ReadFirstChain(signCertFileName);
+ IPrivateKey signRsaPrivateKey = PemFileHelper.ReadFirstKey(signCertFileName, PRIVATE_KEY_PASSWORD);
+ ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
+ MemoryStream preparedDocument = new MemoryStream();
+ using (PdfReader reader = new PdfReader(srcFileName, properties)) {
+ using (Stream outputStream = preparedDocument) {
+ PdfSigner pdfSigner = new PdfSigner(reader, outputStream, new StampingProperties());
+ pdfSigner.SignExternalContainer(new ExternalBlankSignatureContainer(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached
+ ), 5000);
+ }
+ }
+ using (PdfDocument document = new PdfDocument(new PdfReader(new MemoryStream(preparedDocument.ToArray()),
+ properties))) {
+ using (Stream outputStream_1 = FileUtil.GetFileOutputStream(outputFileName)) {
+ PdfSigner.SignDeferred(document, "Signature1", outputStream_1, new PKCS7ExternalSignatureContainer(signRsaPrivateKey
+ , signRsaChain, "SHA-512"));
+ }
+ }
+ NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
+ , properties));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void TwoPhaseSignerWithReaderTest() {
+ String fileName = "twoPhaseSignerWithReaderTest.pdf";
+ String srcFileName = SOURCE_FOLDER + "macEncryptedDoc.pdf";
+ String outputFileName = DESTINATION_FOLDER + fileName;
+ String signCertFileName = CERTS_SRC + "signCertRsa01.pem";
+ String cmpFileName = SOURCE_FOLDER + "cmp_" + fileName;
+ IX509Certificate[] signRsaChain = PemFileHelper.ReadFirstChain(signCertFileName);
+ IPrivateKey signRsaPrivateKey = PemFileHelper.ReadFirstKey(signCertFileName, PRIVATE_KEY_PASSWORD);
+ ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
+ using (PdfReader reader = new PdfReader(FileUtil.GetInputStreamForFile(srcFileName), properties)) {
+ using (MemoryStream outputStream = new MemoryStream()) {
+ PdfTwoPhaseSigner signer = new PdfTwoPhaseSigner(reader, outputStream);
+ SignerProperties signerProperties = new SignerProperties();
+ byte[] digest = signer.PrepareDocumentForSignature(signerProperties, "SHA-512", PdfName.Adobe_PPKLite, PdfName
+ .Adbe_pkcs7_detached, 5000, false);
+ String fieldName = signerProperties.GetFieldName();
+ byte[] signData = SignDigest(digest, signRsaChain, signRsaPrivateKey);
+ using (Stream outputStreamPhase2 = FileUtil.GetFileOutputStream(outputFileName)) {
+ using (PdfReader newReader = new PdfReader(new MemoryStream(outputStream.ToArray()), properties)) {
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(newReader, fieldName, outputStreamPhase2, signData);
+ }
+ }
+ }
+ }
+ NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
+ , properties));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void TwoPhaseSignerWithDocumentTest() {
+ String fileName = "twoPhaseSignerWithDocumentTest.pdf";
+ String srcFileName = SOURCE_FOLDER + "macEncryptedDoc.pdf";
+ String outputFileName = DESTINATION_FOLDER + fileName;
+ String signCertFileName = CERTS_SRC + "signCertRsa01.pem";
+ String cmpFileName = SOURCE_FOLDER + "cmp_" + fileName;
+ IX509Certificate[] signRsaChain = PemFileHelper.ReadFirstChain(signCertFileName);
+ IPrivateKey signRsaPrivateKey = PemFileHelper.ReadFirstKey(signCertFileName, PRIVATE_KEY_PASSWORD);
+ ReaderProperties properties = new ReaderProperties().SetPassword(ENCRYPTION_PASSWORD);
+ using (PdfReader reader = new PdfReader(FileUtil.GetInputStreamForFile(srcFileName), properties)) {
+ using (MemoryStream outputStream = new MemoryStream()) {
+ PdfTwoPhaseSigner signer = new PdfTwoPhaseSigner(reader, outputStream);
+ SignerProperties signerProperties = new SignerProperties();
+ byte[] digest = signer.PrepareDocumentForSignature(signerProperties, "SHA-512", PdfName.Adobe_PPKLite, PdfName
+ .Adbe_pkcs7_detached, 5000, false);
+ String fieldName = signerProperties.GetFieldName();
+ byte[] signData = SignDigest(digest, signRsaChain, signRsaPrivateKey);
+ using (Stream outputStreamPhase2 = FileUtil.GetFileOutputStream(outputFileName)) {
+ using (PdfDocument document = new PdfDocument(new PdfReader(new MemoryStream(outputStream.ToArray()), properties
+ ))) {
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(document, fieldName, outputStreamPhase2, signData);
+ }
+ }
+ }
+ }
+ NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outputFileName, cmpFileName, properties
+ , properties));
+ }
+
+ private byte[] SignDigest(byte[] data, IX509Certificate[] chain, IPrivateKey pk) {
+ PdfPKCS7 sgn = new PdfPKCS7((IPrivateKey)null, chain, "SHA-512", new BouncyCastleDigest(), false);
+ byte[] sh = sgn.GetAuthenticatedAttributeBytes(data, PdfSigner.CryptoStandard.CMS, null, null);
+ PrivateKeySignature pkSign = new PrivateKeySignature(pk, "SHA-512");
+ byte[] signData = pkSign.Sign(sh);
+ sgn.SetExternalSignatureValue(signData, null, pkSign.GetSignatureAlgorithmName(), pkSign.GetSignatureMechanismParameters
+ ());
+ return sgn.GetEncodedPKCS7(data, PdfSigner.CryptoStandard.CMS, null, null, null);
+ }
+ }
+}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/SignDeferredTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/SignDeferredTest.cs
index 272031bc8b..56e49bafa1 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/sign/SignDeferredTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/sign/SignDeferredTest.cs
@@ -136,11 +136,34 @@ public virtual void DeferredHashCalcAndSignTest01() {
IExternalSignatureContainer extSigContainer = new SignDeferredTest.CmsDeferredSigner(signPrivateKey, signChain
);
String sigFieldName = "DeferredSignature1";
- PdfDocument docToSign = new PdfDocument(new PdfReader(srcFileName));
- Stream outStream = FileUtil.GetFileOutputStream(outFileName);
- PdfSigner.SignDeferred(docToSign, sigFieldName, outStream, extSigContainer);
- docToSign.Close();
- outStream.Dispose();
+ using (PdfReader reader = new PdfReader(srcFileName)) {
+ using (Stream outStream = FileUtil.GetFileOutputStream(outFileName)) {
+ PdfSigner.SignDeferred(reader, sigFieldName, outStream, extSigContainer);
+ }
+ }
+ // validate result
+ TestSignUtils.BasicCheckSignedDoc(outFileName, sigFieldName);
+ NUnit.Framework.Assert.IsNull(new CompareTool().CompareVisually(outFileName, cmpFileName, destinationFolder
+ , null));
+ NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outFileName, cmpFileName));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void DeferredDeprecatedApiTest() {
+ String srcFileName = sourceFolder + "templateForSignCMSDeferred.pdf";
+ String outFileName = destinationFolder + "deferredDeprecatedApiTest.pdf";
+ String cmpFileName = sourceFolder + "cmp_deferredDeprecatedApiTest.pdf";
+ String signCertFileName = certsSrc + "signCertRsa01.pem";
+ IX509Certificate[] signChain = PemFileHelper.ReadFirstChain(signCertFileName);
+ IPrivateKey signPrivateKey = PemFileHelper.ReadFirstKey(signCertFileName, password);
+ IExternalSignatureContainer extSigContainer = new SignDeferredTest.CmsDeferredSigner(signPrivateKey, signChain
+ );
+ String sigFieldName = "DeferredSignature1";
+ using (PdfDocument document = new PdfDocument(new PdfReader(srcFileName))) {
+ using (Stream outStream = FileUtil.GetFileOutputStream(outFileName)) {
+ PdfSigner.SignDeferred(document, sigFieldName, outStream, extSigContainer);
+ }
+ }
// validate result
TestSignUtils.BasicCheckSignedDoc(outFileName, sigFieldName);
NUnit.Framework.Assert.IsNull(new CompareTool().CompareVisually(outFileName, cmpFileName, destinationFolder
@@ -181,11 +204,11 @@ public virtual void CalcHashOnDocCreationThenDeferredSignTest01() {
// fill the signature to the presigned document
SignDeferredTest.ReadySignatureSigner extSigContainer = new SignDeferredTest.ReadySignatureSigner(cmsSignature
);
- PdfDocument docToSign = new PdfDocument(new PdfReader(new MemoryStream(preSignedBytes)));
- Stream outStream = FileUtil.GetFileOutputStream(outFileName);
- PdfSigner.SignDeferred(docToSign, sigFieldName, outStream, extSigContainer);
- docToSign.Close();
- outStream.Dispose();
+ using (PdfReader newReader = new PdfReader(new MemoryStream(preSignedBytes))) {
+ using (Stream outStream = FileUtil.GetFileOutputStream(outFileName)) {
+ PdfSigner.SignDeferred(newReader, sigFieldName, outStream, extSigContainer);
+ }
+ }
// validate result
TestSignUtils.BasicCheckSignedDoc(outFileName, sigFieldName);
NUnit.Framework.Assert.IsNull(new CompareTool().CompareVisually(outFileName, cmpFileName, destinationFolder
diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/TwoPhaseSigningTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/TwoPhaseSigningTest.cs
index 93f90c7a01..9529bbafdd 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/sign/TwoPhaseSigningTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/sign/TwoPhaseSigningTest.cs
@@ -104,15 +104,33 @@ public virtual void TestPreparationWithClosedPdfTwoPhaseSigner() {
[NUnit.Framework.Test]
public virtual void TestCompletionWithWrongFieldName() {
+ byte[] signData = new byte[4096];
+ // open prepared document
+ using (PdfReader reader = new PdfReader(new FileInfo(SOURCE_FOLDER + "2PhasePreparedSignature.pdf"
+ ))) {
+ using (Stream signedDoc = new ByteArrayOutputStream()) {
+ // add signature
+ Exception e = NUnit.Framework.Assert.Catch(typeof(PdfException), () => {
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(reader, "wrong" + FIELD_NAME, signedDoc, signData);
+ }
+ );
+ NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(SignExceptionMessageConstant.THERE_IS_NO_FIELD_IN_THE_DOCUMENT_WITH_SUCH_NAME
+ , "wrong" + FIELD_NAME), e.Message);
+ }
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void TestCompletionWithWrongFieldNameAndDeprecatedApiTest() {
byte[] signData = new byte[4096];
// open prepared document
using (PdfDocument preparedDoc = new PdfDocument(new PdfReader(new FileInfo(SOURCE_FOLDER + "2PhasePreparedSignature.pdf"
- )))) {
+ )))) {
using (Stream signedDoc = new ByteArrayOutputStream()) {
// add signature
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfException), () => {
- PdfTwoPhaseSigner.AddSignatureToPreparedDocument(preparedDoc, "wrong" + FIELD_NAME, signedDoc, signData);
- }
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(preparedDoc, "wrong" + FIELD_NAME, signedDoc, signData);
+ }
);
NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(SignExceptionMessageConstant.THERE_IS_NO_FIELD_IN_THE_DOCUMENT_WITH_SUCH_NAME
, "wrong" + FIELD_NAME), e.Message);
@@ -124,12 +142,12 @@ public virtual void TestCompletionWithWrongFieldName() {
public virtual void TestCompletionWithNotEnoughSpace() {
byte[] signData = new byte[20000];
// open prepared document
- using (PdfDocument preparedDoc = new PdfDocument(new PdfReader(new FileInfo(SOURCE_FOLDER + "2PhasePreparedSignature.pdf"
- )))) {
+ using (PdfReader reader = new PdfReader(new FileInfo(SOURCE_FOLDER + "2PhasePreparedSignature.pdf"
+ ))) {
using (Stream signedDoc = new ByteArrayOutputStream()) {
// add signature
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfException), () => {
- PdfTwoPhaseSigner.AddSignatureToPreparedDocument(preparedDoc, FIELD_NAME, signedDoc, signData);
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(reader, FIELD_NAME, signedDoc, signData);
}
);
NUnit.Framework.Assert.AreEqual(SignExceptionMessageConstant.AVAILABLE_SPACE_IS_NOT_ENOUGH_FOR_SIGNATURE,
@@ -151,9 +169,9 @@ public virtual void TestCompletionWithSignatureFieldNotLastOne() {
byte[] signData = new byte[1024];
using (Stream outputStreamPhase2 = FileUtil.GetFileOutputStream(DESTINATION_FOLDER + "2PhaseCompleteCycle.pdf"
)) {
- using (PdfDocument doc = new PdfDocument(new PdfReader(new MemoryStream(outputStream.ToArray())))) {
+ using (PdfReader newReader = new PdfReader(new MemoryStream(outputStream.ToArray()))) {
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfException), () => {
- PdfTwoPhaseSigner.AddSignatureToPreparedDocument(doc, FIELD_NAME, outputStreamPhase2, signData);
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(newReader, FIELD_NAME, outputStreamPhase2, signData);
}
);
NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(SignExceptionMessageConstant.SIGNATURE_WITH_THIS_NAME_IS_NOT_THE_LAST_IT_DOES_NOT_COVER_WHOLE_DOCUMENT
@@ -210,8 +228,8 @@ public virtual void TestCompleteCycle() {
byte[] signData = SignDigest(digest, DIGEST_ALGORITHM);
using (Stream outputStreamPhase2 = FileUtil.GetFileOutputStream(DESTINATION_FOLDER + "2PhaseCompleteCycle.pdf"
)) {
- using (PdfDocument doc = new PdfDocument(new PdfReader(new MemoryStream(outputStream.ToArray())))) {
- PdfTwoPhaseSigner.AddSignatureToPreparedDocument(doc, fieldName, outputStreamPhase2, signData);
+ using (PdfReader newReader = new PdfReader(new MemoryStream(outputStream.ToArray()))) {
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(newReader, fieldName, outputStreamPhase2, signData);
}
}
NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(DESTINATION_FOLDER + "2PhaseCompleteCycle.pdf"
@@ -228,11 +246,11 @@ public virtual void TestCompletion() {
signdataS.Read(signData);
}
// open prepared document
- using (PdfDocument preparedDoc = new PdfDocument(new PdfReader(new FileInfo(SOURCE_FOLDER + "2PhasePreparedSignature.pdf"
- )))) {
+ using (PdfReader reader = new PdfReader(new FileInfo(SOURCE_FOLDER + "2PhasePreparedSignature.pdf"
+ ))) {
using (Stream signedDoc = FileUtil.GetFileOutputStream(DESTINATION_FOLDER + "2PhaseCompletion.pdf")) {
// add signature
- PdfTwoPhaseSigner.AddSignatureToPreparedDocument(preparedDoc, FIELD_NAME, signedDoc, signData);
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(reader, FIELD_NAME, signedDoc, signData);
}
}
NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(DESTINATION_FOLDER + "2PhaseCompletion.pdf"
@@ -262,7 +280,7 @@ public virtual void TestWithCMS() {
cmsToUpdate.GetSignerInfo().SetSignature(signaturedata);
//if needed a time stamp could be added here
//Phase 2.3 add the updated CMS to the document
- PdfTwoPhaseSigner.AddSignatureToPreparedDocument(doc, signatureName, outputStreamPhase2, cmsToUpdate);
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(new PdfReader(new MemoryStream(phaseOneOS.ToArray())), signatureName, outputStreamPhase2, cmsToUpdate);
}
}
// validate signature
@@ -320,8 +338,8 @@ private byte[] PrepareDocumentAndCMS(FileInfo document, ByteArrayOutputStream pr
// now we store signedAttributesToSign together with the prepared document and send
// dataToSign to the signing instance
- using (PdfDocument doc = new PdfDocument(new PdfReader(new MemoryStream(outputStream.ToArray())))) {
- PdfTwoPhaseSigner.AddSignatureToPreparedDocument(doc, fieldName, preparedOS, cms);
+ using (PdfReader newReader = new PdfReader(new MemoryStream(outputStream.ToArray()))) {
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(newReader, fieldName, preparedOS, cms);
}
return dataToSign;
}
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signMacProtectedDocInAppendModeTest_signExternalContainerBlank.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signMacProtectedDocInAppendModeTest_signExternalContainerBlank.pdf
new file mode 100644
index 0000000000..158ab1bd07
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signMacProtectedDocInAppendModeTest_signExternalContainerBlank.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signMacProtectedDocTest_signExternalContainerBlank.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signMacProtectedDocTest_signExternalContainerBlank.pdf
new file mode 100644
index 0000000000..00078686df
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signMacProtectedDocTest_signExternalContainerBlank.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signMacProtectedDocWithSHA3_384Test_signExternalContainerBlank.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signMacProtectedDocWithSHA3_384Test_signExternalContainerBlank.pdf
new file mode 100644
index 0000000000..6fc6a8d3c4
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signMacProtectedDocWithSHA3_384Test_signExternalContainerBlank.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signMacPublicEncryptionDocTest_signExternalContainerBlank.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signMacPublicEncryptionDocTest_signExternalContainerBlank.pdf
new file mode 100644
index 0000000000..324528ee3e
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signMacPublicEncryptionDocTest_signExternalContainerBlank.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signNotMacProtectedDocTest_signExternalContainerBlank.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signNotMacProtectedDocTest_signExternalContainerBlank.pdf
new file mode 100644
index 0000000000..97885c7ea7
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/SignedDocumentWithMacTest/cmp_signNotMacProtectedDocTest_signExternalContainerBlank.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/cmp_signDeferredWithDocumentTest.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/cmp_signDeferredWithDocumentTest.pdf
new file mode 100644
index 0000000000..d94baba4e0
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/cmp_signDeferredWithDocumentTest.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/cmp_signDeferredWithReaderTest.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/cmp_signDeferredWithReaderTest.pdf
new file mode 100644
index 0000000000..ef7ac3368a
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/cmp_signDeferredWithReaderTest.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/cmp_twoPhaseSignerWithDocumentTest.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/cmp_twoPhaseSignerWithDocumentTest.pdf
new file mode 100644
index 0000000000..a77c6fcc21
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/cmp_twoPhaseSignerWithDocumentTest.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/cmp_twoPhaseSignerWithReaderTest.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/cmp_twoPhaseSignerWithReaderTest.pdf
new file mode 100644
index 0000000000..fa361b5b40
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/cmp_twoPhaseSignerWithReaderTest.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/macEncryptedDoc.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/macEncryptedDoc.pdf
new file mode 100644
index 0000000000..f8bffedbdc
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/mac/TwoStepSigningWithMacTest/macEncryptedDoc.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/sign/SignDeferredTest/cmp_deferredDeprecatedApiTest.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/sign/SignDeferredTest/cmp_deferredDeprecatedApiTest.pdf
new file mode 100644
index 0000000000..abcdc7adc6
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/sign/SignDeferredTest/cmp_deferredDeprecatedApiTest.pdf differ
diff --git a/itext/itext.kernel/itext/kernel/utils/IdleOutputStream.cs b/itext/itext.kernel/itext/kernel/utils/IdleOutputStream.cs
index 428e370481..ac2949666e 100644
--- a/itext/itext.kernel/itext/kernel/utils/IdleOutputStream.cs
+++ b/itext/itext.kernel/itext/kernel/utils/IdleOutputStream.cs
@@ -24,55 +24,66 @@ You should have received a copy of the GNU Affero General Public License
using System.IO;
namespace iText.Kernel.Utils {
- //\cond DO_NOT_DOCUMENT
- internal class IdleOutputStream : Stream
+ ///
+ /// Stream implementation which doesn't write anything.
+ ///
+ public class IdleOutputStream : Stream
{
+ ///
public override void Flush()
{
}
+ ///
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
+ ///
public override void SetLength(long value)
{
throw new NotSupportedException();
}
+ ///
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
+ ///
public override void Write(byte[] buffer, int offset, int count)
{
}
+ ///
public override bool CanRead
{
get { return false; }
}
+ ///
public override bool CanSeek
{
get { return false; }
}
+ ///
public override bool CanWrite
{
get { return true; }
}
+ ///
public override long Length
{
get { throw new NotSupportedException(); }
}
+ ///
public override long Position { get; set; }
}
- //\endcond
}
diff --git a/itext/itext.sign/itext/signatures/PadesTwoPhaseSigningHelper.cs b/itext/itext.sign/itext/signatures/PadesTwoPhaseSigningHelper.cs
index c7078208ea..7971033a97 100644
--- a/itext/itext.sign/itext/signatures/PadesTwoPhaseSigningHelper.cs
+++ b/itext/itext.sign/itext/signatures/PadesTwoPhaseSigningHelper.cs
@@ -368,9 +368,8 @@ public virtual void SignCMSContainerWithBaselineBProfile(IExternalSignature exte
, Stream outputStream, String signatureFieldName, CMSContainer cmsContainer) {
SetSignatureAlgorithmAndSignature(externalSignature, cmsContainer);
try {
- using (PdfDocument document = new PdfDocument(inputDocument, stampingProperties)) {
- PdfTwoPhaseSigner.AddSignatureToPreparedDocument(document, signatureFieldName, outputStream, cmsContainer);
- }
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(inputDocument, signatureFieldName, outputStream, cmsContainer
+ );
}
finally {
outputStream.Dispose();
@@ -401,9 +400,8 @@ public virtual void SignCMSContainerWithBaselineTProfile(IExternalSignature exte
cmsContainer.GetSignerInfo().AddUnSignedAttribute(timestampAttribute);
}
try {
- using (PdfDocument document = new PdfDocument(inputDocument, stampingProperties)) {
- PdfTwoPhaseSigner.AddSignatureToPreparedDocument(document, signatureFieldName, outputStream, cmsContainer);
- }
+ PdfTwoPhaseSigner.AddSignatureToPreparedDocument(inputDocument, signatureFieldName, outputStream, cmsContainer
+ );
}
finally {
outputStream.Dispose();
diff --git a/itext/itext.sign/itext/signatures/PdfSigner.cs b/itext/itext.sign/itext/signatures/PdfSigner.cs
index b593ff6125..1c277d370b 100644
--- a/itext/itext.sign/itext/signatures/PdfSigner.cs
+++ b/itext/itext.sign/itext/signatures/PdfSigner.cs
@@ -46,6 +46,7 @@ You should have received a copy of the GNU Affero General Public License
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Annot;
using iText.Kernel.Pdf.Tagutils;
+using iText.Kernel.Utils;
using iText.Kernel.Validation;
using iText.Kernel.Validation.Context;
using iText.Layout.Properties;
@@ -613,7 +614,9 @@ public virtual void SignExternalContainer(IExternalSignatureContainer externalSi
PreClose(exc);
Stream data = GetRangeStream();
byte[] encodedSig = externalSignatureContainer.Sign(data);
- encodedSig = EmbedMacTokenIntoSignatureContainer(encodedSig);
+ if (document.GetDiContainer().GetInstance().IsMacContainerLocated()) {
+ encodedSig = EmbedMacTokenIntoSignatureContainer(encodedSig);
+ }
if (estimatedSize < encodedSig.Length) {
throw new System.IO.IOException(SignExceptionMessageConstant.NOT_ENOUGH_SPACE);
}
@@ -675,7 +678,9 @@ public virtual void Timestamp(ITSAClient tsa, String signatureName) {
throw iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateGeneralSecurityException(e
.Message, e);
}
- tsToken = EmbedMacTokenIntoSignatureContainer(tsToken);
+ if (document.GetDiContainer().GetInstance().IsMacContainerLocated()) {
+ tsToken = EmbedMacTokenIntoSignatureContainer(tsToken);
+ }
if (contentEstimated + 2 < tsToken.Length) {
throw new System.IO.IOException(MessageFormatUtil.Format(SignExceptionMessageConstant.TOKEN_ESTIMATION_SIZE_IS_NOT_LARGE_ENOUGH
, contentEstimated, tsToken.Length));
@@ -696,12 +701,32 @@ public virtual void Timestamp(ITSAClient tsa, String signatureName) {
/// the signature container doing the actual signing. Only the
/// method ExternalSignatureContainer.sign is used
///
+ [System.ObsoleteAttribute(@"SignDeferred(iText.Kernel.Pdf.PdfReader, System.String, System.IO.Stream, IExternalSignatureContainer) should be used instead."
+ )]
public static void SignDeferred(PdfDocument document, String fieldName, Stream outs, IExternalSignatureContainer
externalSignatureContainer) {
PdfSigner.SignatureApplier applier = new PdfSigner.SignatureApplier(document, fieldName, outs);
applier.Apply((a) => externalSignatureContainer.Sign(a.GetDataToSign()));
}
+ /// Signs a PDF where space was already reserved.
+ ///
+ ///
+ ///
+ /// that reads the PDF file
+ ///
+ /// the field to sign. It must be the last field
+ /// the output PDF
+ ///
+ /// the signature container doing the actual signing. Only the
+ /// method ExternalSignatureContainer.sign is used
+ ///
+ public static void SignDeferred(PdfReader reader, String fieldName, Stream outs, IExternalSignatureContainer
+ externalSignatureContainer) {
+ PdfSigner.SignatureApplier applier = new PdfSigner.SignatureApplier(reader, fieldName, outs);
+ applier.Apply((a) => externalSignatureContainer.Sign(a.GetDataToSign()));
+ }
+
/// Processes a CRL list.
/// a Certificate if one of the CrlList implementations needs to retrieve the CRL URL from it.
///
@@ -1243,6 +1268,54 @@ internal virtual PdfSignature CreateSignatureDictionary(bool includeDate) {
}
//\endcond
+//\cond DO_NOT_DOCUMENT
+ internal virtual byte[] EmbedMacTokenIntoSignatureContainer(byte[] signatureContainer) {
+ using (Stream rangeStream = GetRangeStream()) {
+ return EmbedMacTokenIntoSignatureContainer(signatureContainer, rangeStream, document);
+ }
+ }
+//\endcond
+
+//\cond DO_NOT_DOCUMENT
+ internal static byte[] EmbedMacTokenIntoSignatureContainer(byte[] signatureContainer, Stream rangeStream,
+ PdfDocument document) {
+ try {
+ CMSContainer cmsContainer;
+ if (JavaUtil.ArraysEquals(new byte[signatureContainer.Length], signatureContainer)) {
+ // Signature container is empty most likely due two two-step signing process.
+ // We will create blank signature container in order to add MAC in there.
+ cmsContainer = new CMSContainer();
+ SignerInfo signerInfo = new SignerInfo();
+ String digestAlgorithmOid = DigestAlgorithms.GetAllowedDigest(DigestAlgorithms.SHA256);
+ signerInfo.SetDigestAlgorithm(new AlgorithmIdentifier(digestAlgorithmOid));
+ signerInfo.SetSignatureAlgorithm(new AlgorithmIdentifier(OID.RSA));
+ signerInfo.SetSignature("This is a placeholder signature. It's value shall be replaced with a real signature."
+ .GetBytes(System.Text.Encoding.UTF8));
+ cmsContainer.SetSignerInfo(signerInfo);
+ }
+ else {
+ cmsContainer = new CMSContainer(signatureContainer);
+ }
+ // If MAC is in the signature already, we regenerate it anyway.
+ cmsContainer.GetSignerInfo().RemoveUnSignedAttribute(ID_ATTR_PDF_MAC_DATA);
+ IAsn1EncodableVector unsignedVector = FACTORY.CreateASN1EncodableVector();
+ document.DispatchEvent(new SignatureContainerGenerationEvent(unsignedVector, cmsContainer.GetSignerInfo().
+ GetSignatureData(), rangeStream));
+ if (FACTORY.CreateDERSequence(unsignedVector).Size() != 0) {
+ IAsn1Sequence sequence = FACTORY.CreateASN1Sequence(FACTORY.CreateDERSequence(unsignedVector).GetObjectAt(
+ 0));
+ cmsContainer.GetSignerInfo().AddUnSignedAttribute(new CmsAttribute(FACTORY.CreateASN1ObjectIdentifier(sequence
+ .GetObjectAt(0)).GetId(), sequence.GetObjectAt(1).ToASN1Primitive()));
+ return cmsContainer.Serialize();
+ }
+ }
+ catch (Exception exception) {
+ throw new PdfException(SignExceptionMessageConstant.NOT_POSSIBLE_TO_EMBED_MAC_TO_SIGNATURE, exception);
+ }
+ return signatureContainer;
+ }
+//\endcond
+
private static String GetSignerName(IX509Certificate certificate) {
String name = null;
CertificateInfo.X500Name x500name = CertificateInfo.GetSubjectFields(certificate);
@@ -1301,30 +1374,6 @@ protected internal virtual void ApplyAccessibilityProperties(PdfFormField formFi
}
}
- private byte[] EmbedMacTokenIntoSignatureContainer(byte[] signatureContainer) {
- if (document.GetDiContainer().GetInstance().IsMacContainerLocated()) {
- try {
- CMSContainer cmsContainer = new CMSContainer(signatureContainer);
- // If MAC is in the signature already, we regenerate it anyway.
- cmsContainer.GetSignerInfo().RemoveUnSignedAttribute(ID_ATTR_PDF_MAC_DATA);
- IAsn1EncodableVector unsignedVector = FACTORY.CreateASN1EncodableVector();
- document.DispatchEvent(new SignatureContainerGenerationEvent(unsignedVector, cmsContainer.GetSignerInfo().
- GetSignatureData(), GetRangeStream()));
- if (FACTORY.CreateDERSequence(unsignedVector).Size() != 0) {
- IAsn1Sequence sequence = FACTORY.CreateASN1Sequence(FACTORY.CreateDERSequence(unsignedVector).GetObjectAt(
- 0));
- cmsContainer.GetSignerInfo().AddUnSignedAttribute(new CmsAttribute(FACTORY.CreateASN1ObjectIdentifier(sequence
- .GetObjectAt(0)).GetId(), sequence.GetObjectAt(1).ToASN1Primitive()));
- return cmsContainer.Serialize();
- }
- }
- catch (Exception exception) {
- throw new PdfException(SignExceptionMessageConstant.NOT_POSSIBLE_TO_EMBED_MAC_TO_SIGNATURE, exception);
- }
- }
- return signatureContainer;
- }
-
private void ApplyDefaultPropertiesForTheNewField(PdfSignatureFormField sigField) {
SignatureFieldAppearance formFieldElement = GetSignatureAppearance();
PdfFormAnnotation annotation = sigField.GetFirstFormAnnotation();
@@ -1411,6 +1460,8 @@ public interface ISignatureEvent {
internal class SignatureApplier {
private readonly PdfDocument document;
+ private readonly PdfReader reader;
+
private readonly String fieldName;
private readonly Stream outs;
@@ -1419,13 +1470,46 @@ internal class SignatureApplier {
private long[] gaps;
+ public SignatureApplier(PdfReader reader, String fieldName, Stream outs) {
+ this.reader = reader;
+ this.fieldName = fieldName;
+ this.outs = outs;
+ this.document = null;
+ }
+
public SignatureApplier(PdfDocument document, String fieldName, Stream outs) {
this.document = document;
this.fieldName = fieldName;
this.outs = outs;
+ this.reader = null;
}
public virtual void Apply(PdfSigner.ISignatureDataProvider signatureDataProvider) {
+ StampingProperties properties = new StampingProperties().PreserveEncryption();
+ properties.RegisterDependency(typeof(IMacContainerLocator), new SignatureMacContainerLocator());
+ // This IdleOutputStream writer does nothing and only required to be able to apply MAC if needed.
+ using (PdfWriter dummyWriter = new PdfWriter(new IdleOutputStream())) {
+ if (document == null) {
+ using (PdfDocument newDocument = new PdfDocument(reader, dummyWriter, properties)) {
+ Apply(newDocument, signatureDataProvider);
+ }
+ }
+ else {
+ RandomAccessFileOrArray raf = document.GetReader().GetSafeFile();
+ WindowRandomAccessSource source = new WindowRandomAccessSource(raf.CreateSourceView(), 0, raf.Length());
+ using (Stream inputStream = new RASInputStream(source)) {
+ using (PdfReader newReader = new PdfReader(inputStream, document.GetReader().GetPropertiesCopy())) {
+ using (PdfDocument newDocument = new PdfDocument(newReader, dummyWriter, properties)) {
+ Apply(newDocument, signatureDataProvider);
+ }
+ }
+ }
+ }
+ }
+ }
+
+//\cond DO_NOT_DOCUMENT
+ internal virtual void Apply(PdfDocument document, PdfSigner.ISignatureDataProvider signatureDataProvider) {
SignatureUtil signatureUtil = new SignatureUtil(document);
PdfSignature signature = signatureUtil.GetSignature(fieldName);
if (signature == null) {
@@ -1444,6 +1528,12 @@ public virtual void Apply(PdfSigner.ISignatureDataProvider signatureDataProvider
throw new ArgumentException("Gap is not a multiple of 2");
}
byte[] signedContent = signatureDataProvider(this);
+ if (document.GetDiContainer().GetInstance().IsMacContainerLocated()) {
+ RandomAccessSourceFactory fac = new RandomAccessSourceFactory();
+ IRandomAccessSource randomAccessSource = fac.CreateRanged(readerSource, gaps);
+ RASInputStream signedDocumentStream = new RASInputStream(randomAccessSource);
+ signedContent = EmbedMacTokenIntoSignatureContainer(signedContent, signedDocumentStream, document);
+ }
spaceAvailable /= 2;
if (spaceAvailable < signedContent.Length) {
throw new PdfException(SignExceptionMessageConstant.AVAILABLE_SPACE_IS_NOT_ENOUGH_FOR_SIGNATURE);
@@ -1462,6 +1552,7 @@ public virtual void Apply(PdfSigner.ISignatureDataProvider signatureDataProvider
StreamUtil.CopyBytes(readerSource, gaps[2] - 1, gaps[3] + 1, outs);
document.Close();
}
+//\endcond
public virtual Stream GetDataToSign() {
return new RASInputStream(new RandomAccessSourceFactory().CreateRanged(readerSource, gaps));
diff --git a/itext/itext.sign/itext/signatures/PdfTwoPhaseSigner.cs b/itext/itext.sign/itext/signatures/PdfTwoPhaseSigner.cs
index 723e3e46e0..08591a39cd 100644
--- a/itext/itext.sign/itext/signatures/PdfTwoPhaseSigner.cs
+++ b/itext/itext.sign/itext/signatures/PdfTwoPhaseSigner.cs
@@ -111,23 +111,57 @@ public virtual byte[] PrepareDocumentForSignature(SignerProperties signerPropert
/// the field to sign. It must be the last field
/// the output PDF
/// the finalized CMS container
+ [System.ObsoleteAttribute(@"AddSignatureToPreparedDocument(iText.Kernel.Pdf.PdfReader, System.String, System.IO.Stream, iText.Signatures.Cms.CMSContainer) should be used instead."
+ )]
public static void AddSignatureToPreparedDocument(PdfDocument document, String fieldName, Stream outs, CMSContainer
cmsContainer) {
PdfSigner.SignatureApplier applier = new PdfSigner.SignatureApplier(document, fieldName, outs);
applier.Apply((a) => cmsContainer.Serialize());
}
+ /// Adds an existing signature to a PDF where space was already reserved.
+ ///
+ ///
+ ///
+ /// that reads the PDF file
+ ///
+ /// the field to sign. It must be the last field
+ /// the output PDF
+ /// the finalized CMS container
+ public static void AddSignatureToPreparedDocument(PdfReader reader, String fieldName, Stream outs, CMSContainer
+ cmsContainer) {
+ PdfSigner.SignatureApplier applier = new PdfSigner.SignatureApplier(reader, fieldName, outs);
+ applier.Apply((a) => cmsContainer.Serialize());
+ }
+
/// Adds an existing signature to a PDF where space was already reserved.
/// the original PDF
/// the field to sign. It must be the last field
/// the output PDF
/// the bytes for the signed data
+ [System.ObsoleteAttribute(@"AddSignatureToPreparedDocument(iText.Kernel.Pdf.PdfReader, System.String, System.IO.Stream, byte[]) should be used instead."
+ )]
public static void AddSignatureToPreparedDocument(PdfDocument document, String fieldName, Stream outs, byte
[] signedContent) {
PdfSigner.SignatureApplier applier = new PdfSigner.SignatureApplier(document, fieldName, outs);
applier.Apply((a) => signedContent);
}
+ /// Adds an existing signature to a PDF where space was already reserved.
+ ///
+ ///
+ ///
+ /// that reads the PDF file
+ ///
+ /// the field to sign. It must be the last field
+ /// the output PDF
+ /// the bytes for the signed data
+ public static void AddSignatureToPreparedDocument(PdfReader reader, String fieldName, Stream outs, byte[]
+ signedContent) {
+ PdfSigner.SignatureApplier applier = new PdfSigner.SignatureApplier(reader, fieldName, outs);
+ applier.Apply((a) => signedContent);
+ }
+
/// Use the external digest to inject specific digest implementations
/// the IExternalDigest instance to use to generate Digests
///
@@ -173,9 +207,6 @@ private byte[] PrepareDocumentForSignature(SignerProperties signerProperties, IM
}
PdfSigner pdfSigner = CreatePdfSigner(signerProperties);
PdfDocument document = pdfSigner.GetDocument();
- if (document.GetDiContainer().GetInstance().IsMacContainerLocated()) {
- throw new PdfException(SignExceptionMessageConstant.NOT_POSSIBLE_TO_EMBED_MAC_TO_SIGNATURE);
- }
if (document.GetPdfVersion().CompareTo(PdfVersion.PDF_2_0) < 0) {
document.GetCatalog().AddDeveloperExtension(PdfDeveloperExtension.ESIC_1_7_EXTENSIONLEVEL2);
}
@@ -191,6 +222,13 @@ private byte[] PrepareDocumentForSignature(SignerProperties signerProperties, IM
Stream data = pdfSigner.GetRangeStream();
byte[] digest = DigestAlgorithms.Digest(data, messageDigest);
byte[] paddedSig = new byte[estimatedSize];
+ if (document.GetDiContainer().GetInstance().IsMacContainerLocated()) {
+ byte[] encodedSig = pdfSigner.EmbedMacTokenIntoSignatureContainer(paddedSig);
+ if (estimatedSize < encodedSig.Length) {
+ throw new System.IO.IOException(SignExceptionMessageConstant.NOT_ENOUGH_SPACE);
+ }
+ Array.Copy(encodedSig, 0, paddedSig, 0, encodedSig.Length);
+ }
PdfDictionary dic2 = new PdfDictionary();
dic2.Put(PdfName.Contents, new PdfString(paddedSig).SetHexWriting(true));
pdfSigner.Close(dic2);
diff --git a/itext/itext.sign/itext/signatures/cms/SignerInfo.cs b/itext/itext.sign/itext/signatures/cms/SignerInfo.cs
index 71a175dd24..932f060914 100644
--- a/itext/itext.sign/itext/signatures/cms/SignerInfo.cs
+++ b/itext/itext.sign/itext/signatures/cms/SignerInfo.cs
@@ -402,8 +402,10 @@ internal virtual IDerSequence GetAsDerSequence(bool estimationRun) {
signerInfoV.Add(BC_FACTORY.CreateASN1Integer(GetCmsVersion()));
// sid
IAsn1EncodableVector issuerAndSerialNumberV = BC_FACTORY.CreateASN1EncodableVector();
- issuerAndSerialNumberV.Add(CertificateInfo.GetIssuer(signerCertificate.GetTbsCertificate()));
- issuerAndSerialNumberV.Add(BC_FACTORY.CreateASN1Integer(signerCertificate.GetSerialNumber()));
+ if (signerCertificate != null) {
+ issuerAndSerialNumberV.Add(CertificateInfo.GetIssuer(signerCertificate.GetTbsCertificate()));
+ issuerAndSerialNumberV.Add(BC_FACTORY.CreateASN1Integer(signerCertificate.GetSerialNumber()));
+ }
signerInfoV.Add(BC_FACTORY.CreateDERSequence(issuerAndSerialNumberV));
// digest algorithm
IAsn1EncodableVector digestalgorithmV = BC_FACTORY.CreateASN1EncodableVector();
diff --git a/itext/itext.sign/itext/signatures/exceptions/SignExceptionMessageConstant.cs b/itext/itext.sign/itext/signatures/exceptions/SignExceptionMessageConstant.cs
index 1595678b1d..8b04738c43 100644
--- a/itext/itext.sign/itext/signatures/exceptions/SignExceptionMessageConstant.cs
+++ b/itext/itext.sign/itext/signatures/exceptions/SignExceptionMessageConstant.cs
@@ -90,7 +90,7 @@ public sealed class SignExceptionMessageConstant {
public const String NOT_A_VALID_PKCS7_OBJECT_NOT_SIGNED_DATA = "Not a valid PKCS#7 object - not signed " +
"data.";
- public const String NOT_ENOUGH_SPACE = "Not enough space.";
+ public const String NOT_ENOUGH_SPACE = "Not enough space allocated for the signature.";
public const String NOT_POSSIBLE_TO_EMBED_MAC_TO_SIGNATURE = "It was not possible to embed MAC token into signature. Most likely signature container is empty.";
diff --git a/port-hash b/port-hash
index 653f9be508..6ef01d1ffb 100644
--- a/port-hash
+++ b/port-hash
@@ -1 +1 @@
-8c0e38d0ef4a27061abdb53952d163b387ba005c
+5309178a5193a7909c6a53f405e526a80b29540b
\ No newline at end of file