diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentIdTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentIdTest.cs index eae63a3c71..2346243b9e 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentIdTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentIdTest.cs @@ -22,7 +22,7 @@ You should have received a copy of the GNU Affero General Public License */ using System; using System.IO; -using iText.Commons.Bouncycastle.Crypto; +using iText.Commons.Digest; using iText.IO.Source; using iText.Kernel.Exceptions; using iText.Kernel.Pdf.Canvas; @@ -67,7 +67,7 @@ public virtual void ChangeIdTest() { [NUnit.Framework.Test] public virtual void ChangeIdTest02() { MemoryStream baos = new MemoryStream(); - IDigest md5; + IMessageDigest md5; try { md5 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest("MD5"); } @@ -94,7 +94,7 @@ public virtual void ChangeIdTest02() { public virtual void ChangeIdTest03() { MemoryStream baosInitial = new MemoryStream(); MemoryStream baosModified = new MemoryStream(); - IDigest md5; + IMessageDigest md5; try { md5 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest("MD5"); } @@ -138,7 +138,7 @@ public virtual void ChangeIdTest03() { [NUnit.Framework.Test] public virtual void FetchReaderIdTest() { MemoryStream baos = new MemoryStream(); - IDigest md5; + IMessageDigest md5; try { md5 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest("MD5"); } @@ -165,7 +165,7 @@ public virtual void FetchReaderIdTest() { [NUnit.Framework.Test] public virtual void WriterPropertiesPriorityTest() { MemoryStream baos = new MemoryStream(); - IDigest md5; + IMessageDigest md5; try { md5 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest("MD5"); } diff --git a/itext.tests/itext.sign.tests/itext/signatures/BouncyCastleDigestUnitTest.cs b/itext.tests/itext.sign.tests/itext/signatures/BouncyCastleDigestUnitTest.cs new file mode 100644 index 0000000000..fa96ba7306 --- /dev/null +++ b/itext.tests/itext.sign.tests/itext/signatures/BouncyCastleDigestUnitTest.cs @@ -0,0 +1,151 @@ +/* +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 iText.Bouncycastleconnector; +using iText.Commons.Bouncycastle; +using iText.Commons.Bouncycastle.Security; +using iText.Commons.Digest; +using iText.Test; + +namespace iText.Signatures { + [NUnit.Framework.Category("BouncyCastleUnitTest")] + public class BouncyCastleDigestUnitTest : ExtendedITextTest { + private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory(); + private static readonly bool FIPS_MODE = FIPS_MODE = "BCFIPS".Equals(FACTORY.GetProviderName()); + + [NUnit.Framework.Test] + public virtual void GetMessageDigestMD2Test() { + if (FIPS_MODE) { + NUnit.Framework.Assert.Catch(typeof(AbstractGeneralSecurityException), () => + new BouncyCastleDigest().GetMessageDigest("MD2")); + } + else { + GetMessageDigestTest("MD2", "MD2"); + } + } + + [NUnit.Framework.Test] + public virtual void GetMessageDigestMD5Test() { + GetMessageDigestTest("MD5", "MD5"); + } + + [NUnit.Framework.Test] + public virtual void GetMessageDigestSHA1Test() { + GetMessageDigestTest("SHA1", "SHA-1"); + } + + [NUnit.Framework.Test] + public virtual void GetMessageDigestSHA224Test() { + if (FIPS_MODE) { + NUnit.Framework.Assert.Catch(typeof(AbstractGeneralSecurityException), () => + new BouncyCastleDigest().GetMessageDigest("SHA-224")); + } + else { + GetMessageDigestTest("SHA224", "SHA-224"); + } + } + + [NUnit.Framework.Test] + public virtual void GetMessageDigestSHA256Test() { + GetMessageDigestTest("SHA256", "SHA-256"); + } + + [NUnit.Framework.Test] + public virtual void GetMessageDigestSHA384Test() { + GetMessageDigestTest("SHA384", "SHA-384"); + } + + [NUnit.Framework.Test] + public virtual void GetMessageDigestSHA512Test() { + GetMessageDigestTest("SHA512", "SHA-512"); + } + + [NUnit.Framework.Test] + public virtual void GetMessageDigestRIPEMD128Test() { + if (FIPS_MODE) { + NUnit.Framework.Assert.Catch(typeof(AbstractGeneralSecurityException), () => + new BouncyCastleDigest().GetMessageDigest("RIPEMD128")); + } + else { + GetMessageDigestTest("RIPEMD128", "RIPEMD128"); + } + } + + [NUnit.Framework.Test] + public virtual void GetMessageDigestRIPEMD160Test() { + if (FIPS_MODE) { + NUnit.Framework.Assert.Catch(typeof(AbstractGeneralSecurityException), () => + new BouncyCastleDigest().GetMessageDigest("RIPEMD160")); + } + else { + GetMessageDigestTest("RIPEMD160", "RIPEMD160"); + } + } + + [NUnit.Framework.Test] + public virtual void GetMessageDigestRIPEMD256Test() { + if (FIPS_MODE) { + NUnit.Framework.Assert.Catch(typeof(AbstractGeneralSecurityException), () => + new BouncyCastleDigest().GetMessageDigest("RIPEMD256")); + } + else { + GetMessageDigestTest("RIPEMD256", "RIPEMD256"); + } + } + + [NUnit.Framework.Test] + public virtual void GetMessageDigestGOST3411Test() { + if (FIPS_MODE) { + NUnit.Framework.Assert.Catch(typeof(AbstractGeneralSecurityException), () => + new BouncyCastleDigest().GetMessageDigest("Gost3411")); + } + else { + GetMessageDigestTest("Gost3411", "Gost3411"); + } + } + + [NUnit.Framework.Test] + public virtual void GetMessageDigestNullTest() { + IExternalDigest digest = new BouncyCastleDigest(); + NUnit.Framework.Assert.Catch(typeof(ArgumentException), () => digest.GetMessageDigest(null)); + } + + [NUnit.Framework.Test] + public virtual void GetMessageDigestUnknownTest() { + IExternalDigest digest = new BouncyCastleDigest(); + if (FIPS_MODE) { + NUnit.Framework.Assert.Catch(typeof(AbstractGeneralSecurityException), () => digest.GetMessageDigest("unknown")); + } + else { + NUnit.Framework.Assert.Catch(typeof(AbstractSecurityUtilityException), + () => digest.GetMessageDigest("unknown")); + } + } + + private static void GetMessageDigestTest(String hashAlgorithm, String expectedDigestAlgorithm) { + IMessageDigest digest = new BouncyCastleDigest().GetMessageDigest(hashAlgorithm); + NUnit.Framework.Assert.IsNotNull(digest); + NUnit.Framework.Assert.AreEqual(expectedDigestAlgorithm, digest.GetAlgorithmName()); + } + } +} diff --git a/itext.tests/itext.sign.tests/itext/signatures/PdfPKCS7Test.cs b/itext.tests/itext.sign.tests/itext/signatures/PdfPKCS7Test.cs index 9369ce1a08..8dbbce2303 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/PdfPKCS7Test.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/PdfPKCS7Test.cs @@ -45,7 +45,7 @@ public virtual void UnknownHashAlgorithmTest() { // only the hash algorithm is altered String hashAlgorithm = ""; Exception e = NUnit.Framework.Assert.Catch(typeof(PdfException), () => new PdfPKCS7(null, chain, hashAlgorithm - , false)); + , new BouncyCastleDigest(), false)); NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(SignExceptionMessageConstant.UNKNOWN_HASH_ALGORITHM , hashAlgorithm), e.Message); } @@ -67,7 +67,7 @@ public virtual void SimpleCreationTest() { [NUnit.Framework.Test] public virtual void SimpleCreationWithPrivateKeyTest() { String hashAlgorithm = DigestAlgorithms.SHA256; - PdfPKCS7 pkcs7 = new PdfPKCS7(pk, chain, hashAlgorithm, false); + PdfPKCS7 pkcs7 = new PdfPKCS7(pk, chain, hashAlgorithm, new BouncyCastleDigest(), false); String expectedOid = DigestAlgorithms.GetAllowedDigest(hashAlgorithm); NUnit.Framework.Assert.AreEqual(expectedOid, pkcs7.GetDigestAlgorithmOid()); NUnit.Framework.Assert.AreEqual(chain[0], pkcs7.GetSigningCertificate()); @@ -79,7 +79,8 @@ public virtual void SimpleCreationWithPrivateKeyTest() { public virtual void NotAvailableSignatureTest() { String hashAlgorithm = "GOST3411"; // Throws different exceptions on .net and java, bc/bcfips - NUnit.Framework.Assert.Catch(typeof(Exception), () => new PdfPKCS7(pk, chain, hashAlgorithm, false)); + NUnit.Framework.Assert.Catch(typeof(Exception), () => new PdfPKCS7(pk, chain, hashAlgorithm, new BouncyCastleDigest + (), false)); } [NUnit.Framework.Test] @@ -232,7 +233,7 @@ public virtual void IsRevocationValidExceptionDuringValidationTest() { [NUnit.Framework.Test] public virtual void GetEncodedPkcs1Test() { String hashAlgorithm = DigestAlgorithms.SHA256; - PdfPKCS7 pkcs7 = new PdfPKCS7(pk, chain, hashAlgorithm, true); + PdfPKCS7 pkcs7 = new PdfPKCS7(pk, chain, hashAlgorithm, new BouncyCastleDigest(), true); byte[] bytes = pkcs7.GetEncodedPKCS1(); byte[] cmpBytes = File.ReadAllBytes(System.IO.Path.Combine(SOURCE_FOLDER + "cmpBytesPkcs1.txt")); IAsn1OctetString outOctetString = BOUNCY_CASTLE_FACTORY.CreateASN1OctetString(bytes); @@ -243,7 +244,7 @@ public virtual void GetEncodedPkcs1Test() { [NUnit.Framework.Test] public virtual void GetEncodedPkcs1NullPrivateKeyTest() { String hashAlgorithm = DigestAlgorithms.SHA256; - PdfPKCS7 pkcs7 = new PdfPKCS7(null, chain, hashAlgorithm, true); + PdfPKCS7 pkcs7 = new PdfPKCS7(null, chain, hashAlgorithm, new BouncyCastleDigest(), true); Exception exception = NUnit.Framework.Assert.Catch(typeof(PdfException), () => pkcs7.GetEncodedPKCS1()); NUnit.Framework.Assert.AreEqual(KernelExceptionMessageConstant.UNKNOWN_PDF_EXCEPTION, exception.Message); } @@ -251,7 +252,7 @@ public virtual void GetEncodedPkcs1NullPrivateKeyTest() { [NUnit.Framework.Test] public virtual void GetEncodedPkcs7UnknownExceptionTest() { String hashAlgorithm = DigestAlgorithms.SHA256; - PdfPKCS7 pkcs7 = new PdfPKCS7(pk, chain, hashAlgorithm, true); + PdfPKCS7 pkcs7 = new PdfPKCS7(pk, chain, hashAlgorithm, new BouncyCastleDigest(), true); TestTsaClient testTsa = new TestTsaClient(JavaUtil.ArraysAsList(chain), pk); Exception exception = NUnit.Framework.Assert.Catch(typeof(PdfException), () => pkcs7.GetEncodedPKCS7(null, PdfSigner.CryptoStandard.CMS, testTsa, null, null)); @@ -261,7 +262,7 @@ public virtual void GetEncodedPkcs7UnknownExceptionTest() { [NUnit.Framework.Test] public virtual void GetEncodedPkcs7Test() { String hashAlgorithm = DigestAlgorithms.SHA256; - PdfPKCS7 pkcs7 = new PdfPKCS7(pk, chain, hashAlgorithm, true); + PdfPKCS7 pkcs7 = new PdfPKCS7(pk, chain, hashAlgorithm, new BouncyCastleDigest(), true); byte[] bytes = pkcs7.GetEncodedPKCS7(); byte[] cmpBytes = File.ReadAllBytes(System.IO.Path.Combine(SOURCE_FOLDER + "cmpBytesPkcs7.txt")); IAsn1Object outStream = BOUNCY_CASTLE_FACTORY.CreateASN1Primitive(bytes); @@ -273,7 +274,7 @@ public virtual void GetEncodedPkcs7Test() { [NUnit.Framework.Test] public virtual void GetEncodedPkcs7WithRevocationInfoTest() { String hashAlgorithm = DigestAlgorithms.SHA256; - PdfPKCS7 pkcs7 = new PdfPKCS7(pk, chain, hashAlgorithm, true); + PdfPKCS7 pkcs7 = new PdfPKCS7(pk, chain, hashAlgorithm, new BouncyCastleDigest(), true); pkcs7.GetSignedDataCRLs().Add(SignTestPortUtil.ParseCrlFromStream(new FileStream(SOURCE_FOLDER + "firstCrl.bin" , FileMode.Open, FileAccess.Read))); pkcs7.GetSignedDataOcsps().Add(BOUNCY_CASTLE_FACTORY.CreateBasicOCSPResponse(BOUNCY_CASTLE_FACTORY.CreateASN1InputStream @@ -309,7 +310,7 @@ public virtual void VerifyBrainpoolSha2SignatureTest() { // PdfPKCS7 is created here the same way it's done in PdfSigner#signDetached private static PdfPKCS7 CreateSimplePdfPKCS7() { - return new PdfPKCS7(null, chain, DigestAlgorithms.SHA256, false); + return new PdfPKCS7(null, chain, DigestAlgorithms.SHA256, new BouncyCastleDigest(), false); } private String SerializedAsString(byte[] serialized) { diff --git a/itext.tests/itext.sign.tests/itext/signatures/PdfSignerUnitTest.cs b/itext.tests/itext.sign.tests/itext/signatures/PdfSignerUnitTest.cs index 100a241502..47ba58672d 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/PdfSignerUnitTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/PdfSignerUnitTest.cs @@ -118,7 +118,8 @@ public virtual void SignWithFieldLockNotNullTest() { signer.SetPageRect(new Rectangle(100, 100, 10, 10)); signer.fieldLock = new PdfSigFieldLock(); IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); NUnit.Framework.Assert.IsTrue(signer.closed); } @@ -127,9 +128,10 @@ public virtual void SignDetachedWhenAlreadySignedIsNotPossibleTest() { PdfSigner signer = new PdfSigner(new PdfReader(new MemoryStream(CreateSimpleDocument())), new ByteArrayOutputStream (), new StampingProperties()); IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); - Exception e = NUnit.Framework.Assert.Catch(typeof(PdfException), () => signer.SignDetached(pks, chain, null - , null, null, 0, PdfSigner.CryptoStandard.CADES)); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); + Exception e = NUnit.Framework.Assert.Catch(typeof(PdfException), () => signer.SignDetached(new BouncyCastleDigest + (), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES)); NUnit.Framework.Assert.AreEqual(SignExceptionMessageConstant.THIS_INSTANCE_OF_PDF_SIGNER_ALREADY_CLOSED, e .Message); } @@ -139,7 +141,8 @@ public virtual void SignExternalWhenAlreadySignedIsNotPossibleTest() { PdfSigner signer = new PdfSigner(new PdfReader(new MemoryStream(CreateSimpleDocument())), new ByteArrayOutputStream (), new StampingProperties()); IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); Exception e = NUnit.Framework.Assert.Catch(typeof(PdfException), () => signer.SignExternalContainer(new ExternalBlankSignatureContainer (new PdfDictionary()), 0)); NUnit.Framework.Assert.AreEqual(SignExceptionMessageConstant.THIS_INSTANCE_OF_PDF_SIGNER_ALREADY_CLOSED, e diff --git a/itext.tests/itext.sign.tests/itext/signatures/PdfTwoPhaseSignerUnitTest.cs b/itext.tests/itext.sign.tests/itext/signatures/PdfTwoPhaseSignerUnitTest.cs index ccad772b59..c3c0d891c0 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/PdfTwoPhaseSignerUnitTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/PdfTwoPhaseSignerUnitTest.cs @@ -70,6 +70,24 @@ public virtual void PrepareDocumentTestWithSHA256() { NUnit.Framework.Assert.AreEqual(estimatedSize, signature.GetContents().GetValueBytes().Length); } + [NUnit.Framework.Test] + public virtual void PrepareDocumentTestWithExternalDigest() { + 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.SetExternalDigest(new BouncyCastleDigest()); + byte[] digest = 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); + SignatureUtil signatureUtil = new SignatureUtil(resultDoc); + PdfSignature signature = signatureUtil.GetSignature(fieldName); + NUnit.Framework.Assert.AreEqual(estimatedSize, signature.GetContents().GetValueBytes().Length); + } + [NUnit.Framework.Test] public virtual void AddSignatureToPreparedDocumentTest() { PdfReader reader = new PdfReader(new MemoryStream(CreateSimpleDocument())); diff --git a/itext.tests/itext.sign.tests/itext/signatures/TSAClientBouncyCastleTest.cs b/itext.tests/itext.sign.tests/itext/signatures/TSAClientBouncyCastleTest.cs index e78fadf319..a2ab5253ac 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/TSAClientBouncyCastleTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/TSAClientBouncyCastleTest.cs @@ -27,6 +27,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Bouncycastle.Cert; using iText.Commons.Bouncycastle.Crypto; using iText.Commons.Bouncycastle.Tsp; +using iText.Commons.Digest; using iText.Commons.Utils; using iText.Kernel.Exceptions; using iText.Signatures.Exceptions; @@ -124,7 +125,7 @@ public virtual void GetMessageDigestTest() { int tokenSizeEstimate = 4096; TSAClientBouncyCastle tsaClientBouncyCastle = new TSAClientBouncyCastle(url, userName, password, tokenSizeEstimate , digestAlgorithm); - IDigest digest = tsaClientBouncyCastle.GetMessageDigest(); + IMessageDigest digest = tsaClientBouncyCastle.GetMessageDigest(); NUnit.Framework.Assert.IsNotNull(digest); NUnit.Framework.Assert.AreEqual(digestAlgorithm, digest.GetAlgorithmName()); } diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/AnnotationsSigningTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/AnnotationsSigningTest.cs index 067fb81d18..7d5b1b2f43 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/AnnotationsSigningTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/AnnotationsSigningTest.cs @@ -145,7 +145,7 @@ protected internal virtual void Sign(String src, String name, String dest, IX509 } // Creating the signature IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm); - signer.SignDetached(pks, chain, null, null, null, 0, subfilter); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, subfilter); } private static IDictionary> GetTestMap(Rectangle ignoredArea) { diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/EncryptedSigningTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/EncryptedSigningTest.cs index 9bffa81b80..a58c9f5586 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/EncryptedSigningTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/EncryptedSigningTest.cs @@ -78,7 +78,8 @@ public virtual void SignEncryptedPdfTest() { signer.SetFieldName(fieldName); // Creating the signature IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); //Password to open out and cmp files are the same ReaderProperties properties = new ReaderProperties().SetPassword(ownerPass); NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outPdf, cmpPdf, properties, properties @@ -97,7 +98,8 @@ public virtual void SignCertificateSecurityPdfTest() { .UseAppendMode()); // Creating the signature IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); ReaderProperties properties = new ReaderProperties().SetPublicKeySecurityParams(chain[0], pk); //Public key to open out and cmp files are the same NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outPdf, cmpPdf, properties, properties diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/IsoSignatureExtensionsRoundtripTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/IsoSignatureExtensionsRoundtripTest.cs index a4a083e8ea..f5f7a56f07 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/IsoSignatureExtensionsRoundtripTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/IsoSignatureExtensionsRoundtripTest.cs @@ -236,14 +236,14 @@ public virtual void TestIsoExtensionsWithMultipleSignatures() { IExternalSignature pks = new PrivateKeySignature(signPrivateKey, DigestAlgorithms.SHA3_256); PdfSigner signer = new PdfSigner(new PdfReader(in1), baos1, new StampingProperties()); signer.SetFieldName("Signature1"); - signer.SignDetached(pks, signChain1, null, null, null, 0, PdfSigner.CryptoStandard.CMS); + signer.SignDetached(new BouncyCastleDigest(), pks, signChain1, null, null, null, 0, PdfSigner.CryptoStandard.CMS); } using (Stream in2 = new MemoryStream(baos1.ToArray())) { IPrivateKey signPrivateKey = ReadUnencryptedPrivateKey(System.IO.Path.Combine(SOURCE_FOLDER, keySample2 + ".key.pem")); IExternalSignature pks = new PrivateKeySignature(signPrivateKey, DigestAlgorithms.SHA512); PdfSigner signer = new PdfSigner(new PdfReader(in2), baos2, new StampingProperties()); signer.SetFieldName("Signature2"); - signer.SignDetached(pks, signChain2, null, null, null, 0, PdfSigner.CryptoStandard.CMS); + signer.SignDetached(new BouncyCastleDigest(), pks, signChain2, null, null, null, 0, PdfSigner.CryptoStandard.CMS); } CheckIsoExtensions(baos2.ToArray(), JavaUtil.ArraysAsList(32001, 32002)); } @@ -286,7 +286,7 @@ private void DoSign(String keySampleName, String digestAlgo, String signatureAlg signer.SetFieldName(SIGNATURE_FIELD); signer.GetSignatureAppearance().SetPageRect(new Rectangle(50, 650, 200, 100)).SetReason("Test").SetLocation ("TestCity").SetLayer2Text("Approval test signature.\nCreated by iText."); - signer.SignDetached(pks, signChain, null, null, null, 0, PdfSigner.CryptoStandard.CMS); + signer.SignDetached(new BouncyCastleDigest(), pks, signChain, null, null, null, 0, PdfSigner.CryptoStandard.CMS); } private void DoVerify(String fileName, DerObjectIdentifier expectedSigAlgoIdentifier) { diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/LtvSigTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/LtvSigTest.cs index b8005b5c4d..1b69f1501d 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/LtvSigTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/LtvSigTest.cs @@ -104,7 +104,7 @@ public virtual void LtvEnabledSingleSignatureNoCrlDataTest() { PdfSigner signer = new PdfSigner(new PdfReader(srcFileName), new FileStream(ltvFileName, FileMode.Create), new StampingProperties()); signer.SetFieldName("Signature1"); - signer.SignDetached(pks, signChain, crlNotAvailableList, testOcspClient, testTsa, 0, PdfSigner.CryptoStandard + signer.SignDetached(new BouncyCastleDigest(), pks, signChain, crlNotAvailableList, testOcspClient, testTsa, 0, PdfSigner.CryptoStandard .CADES); NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(ltvFileName, compareFile)); } @@ -138,7 +138,7 @@ public virtual void LtvEnabledSingleSignatureNoOcspDataTest() { PdfSigner signer = new PdfSigner(new PdfReader(srcFileName), new FileStream(ltvFileName, FileMode.Create), new StampingProperties()); signer.SetFieldName("Signature1"); - signer.SignDetached(pks, signChain, JavaCollectionsUtil.SingletonList(testCrlClient), null, testTsa + signer.SignDetached(new BouncyCastleDigest(), pks, signChain, JavaCollectionsUtil.SingletonList(testCrlClient), null, testTsa , 0, PdfSigner.CryptoStandard.CADES); NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(ltvFileName, compareFile)); } diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/PadesSignatureLevelTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/PadesSignatureLevelTest.cs index 04cc49979d..64b8f0e45c 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/PadesSignatureLevelTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/PadesSignatureLevelTest.cs @@ -77,7 +77,7 @@ public virtual void PadesSignatureLevelTTest01() { signer.GetSignatureAppearance().SetPageRect(new Rectangle(50, 650, 200, 100)).SetReason("Test").SetLocation ("TestCity").SetLayer2Text("Approval test signature.\nCreated by iText."); TestTsaClient testTsa = new TestTsaClient(JavaUtil.ArraysAsList(tsaChain), tsaPrivateKey); - signer.SignDetached(pks, signRsaChain, null, null, testTsa, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, signRsaChain, null, null, testTsa, 0, PdfSigner.CryptoStandard.CADES); TestSignUtils.BasicCheckSignedDoc(destinationFolder + "padesSignatureLevelTTest01.pdf", "Signature1"); NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outFileName, cmpFileName)); } diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/Pdf20SigningTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/Pdf20SigningTest.cs index 7cdfac5abb..11e129eacb 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/Pdf20SigningTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/Pdf20SigningTest.cs @@ -160,7 +160,7 @@ protected internal virtual void Sign(String src, String name, String dest, IX509 signer.SetFieldName(name); // Creating the signature IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm); - signer.SignDetached(pks, chain, null, null, null, 0, subfilter); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, subfilter); } protected internal virtual void Sign(String src, String name, String dest, IX509Certificate[] chain, IPrivateKey @@ -186,7 +186,7 @@ protected internal virtual void Sign(String src, String name, String dest, IX509 } // Creating the signature IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm); - signer.SignDetached(pks, chain, null, null, null, 0, subfilter); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, subfilter); } protected internal virtual void Sign(String src, String name, String dest, IX509Certificate[] chain, IPrivateKey diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/PdfASigningTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/PdfASigningTest.cs index 7d61d020cf..dc60162022 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/PdfASigningTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/PdfASigningTest.cs @@ -100,7 +100,8 @@ public virtual void SigningPdfA2DocumentTest() { signer.SetFieldLockDict(new PdfSigFieldLock()); signer.SetCertificationLevel(PdfSigner.CERTIFIED_NO_CHANGES_ALLOWED); IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); NUnit.Framework.Assert.IsNull(new VeraPdfValidator().Validate(@out)); } @@ -152,8 +153,8 @@ public virtual void FailedSigningPdfA2DocumentTest() { signer.SetPageRect(rect).GetSignatureAppearance().SetReason("pdfA test").SetLocation("TestCity").SetLayer2Font (font).SetReuseAppearance(false); IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => signer.SignDetached(pks - , chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES)); + Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => signer.SignDetached(new + BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES)); NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(PdfaExceptionMessageConstant.ALL_THE_FONTS_MUST_BE_EMBEDDED_THIS_ONE_IS_NOT_0 , "Helvetica"), e.Message); } @@ -190,7 +191,7 @@ protected internal virtual void Sign(String src, String name, String dest, IX509 } // Creating the signature IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm); - signer.SignDetached(pks, chain, null, null, null, 0, subfilter); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, subfilter); } private static IDictionary> GetTestMap(Rectangle ignoredArea) { diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/PdfSignatureAppearanceTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/PdfSignatureAppearanceTest.cs index 542178fdad..7ed14df636 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/PdfSignatureAppearanceTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/PdfSignatureAppearanceTest.cs @@ -140,7 +140,8 @@ public virtual void TestSigningInAppendModeWithHybridDocument() { (1).SetSignatureAppearance(appearance); signer.SetCertificationLevel(PdfSigner.NOT_CERTIFIED); IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); // Make sure iText can open the document new PdfDocument(new PdfReader(dest)).Close(); // Assert that the document can be rendered correctly @@ -162,7 +163,8 @@ public virtual void FontColorTest01() { (ColorConstants.RED).SetContent("Verified and signed by me.")); // Creating the signature IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); NUnit.Framework.Assert.IsNull(new CompareTool().CompareVisually(dest, SOURCE_FOLDER + "cmp_" + fileName, DESTINATION_FOLDER , "diff_")); } @@ -204,7 +206,8 @@ public virtual void SignExistingNotMergedFieldNotReusedAPTest() { .GetFieldName()).SetContent("Verified and signed by me.")); signer.GetSignatureField().SetReuseAppearance(false); IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); NUnit.Framework.Assert.IsNull(new CompareTool().CompareVisually(dest, SOURCE_FOLDER + "cmp_" + fileName, DESTINATION_FOLDER , "diff_")); } @@ -225,7 +228,8 @@ public virtual void SignExistingNotMergedFieldReusedAPTest() { signer.SetReason("Test 1").SetLocation("TestCity").SetSignatureAppearance(appearance); signer.GetSignatureField().SetReuseAppearance(true); IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); NUnit.Framework.Assert.IsNull(new CompareTool().CompareVisually(dest, SOURCE_FOLDER + "cmp_" + fileName, DESTINATION_FOLDER , "diff_")); } @@ -244,7 +248,8 @@ public virtual void SignExistingNotMergedFieldReusedAPEntryNDicTest() { .GetFieldName()).SetContent("Verified and signed by me.")); signer.GetSignatureField().SetReuseAppearance(true); IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); NUnit.Framework.Assert.IsNull(new CompareTool().CompareVisually(dest, SOURCE_FOLDER + "cmp_" + fileName, DESTINATION_FOLDER , "diff_")); } @@ -275,7 +280,8 @@ public virtual void Layer0Test() { (ColorConstants.BLACK).Circle(50, 50, 50).FillStroke().RestoreState(); // Signing IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); CompareSignatureAppearances(dest, SOURCE_FOLDER + "cmp_" + fileName); } @@ -297,7 +303,8 @@ public virtual void Layer0WithImageTest() { appearance.SetLayer2Text("Hello"); // Signing IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); CompareSignatureAppearances(dest, SOURCE_FOLDER + "cmp_" + fileName); } @@ -320,7 +327,8 @@ public virtual void Layer0WithImageAndPositiveImageScaleTest() { appearance.SetLayer2Text("Hello"); // Signing IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); CompareSignatureAppearances(dest, SOURCE_FOLDER + "cmp_" + fileName); } @@ -343,7 +351,8 @@ public virtual void Layer0WithImageAndNegativeImageScaleTest() { appearance.SetLayer2Text("Hello"); // Signing IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); CompareSignatureAppearances(dest, SOURCE_FOLDER + "cmp_" + fileName); } @@ -370,7 +379,8 @@ public virtual void Layer2Test() { (ColorConstants.BLACK).Circle(50, 50, 50).FillStroke().RestoreState(); // Signing IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); CompareSignatureAppearances(dest, SOURCE_FOLDER + "cmp_" + fileName); } @@ -394,7 +404,8 @@ public virtual void CreateAndSignSignatureFieldTest() { signer.SetReason("Appearance is tested").SetLocation("TestCity").SetSignatureAppearance(appearance); // Signing IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); CompareSignatureAppearances(dest, SOURCE_FOLDER + "cmp_createdAndSignedSignatureField.pdf"); } @@ -413,7 +424,8 @@ public virtual void SignExistedSignatureFieldTest() { signer.GetSignatureField().SetReuseAppearance(true); // Signing IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); CompareSignatureAppearances(dest, SOURCE_FOLDER + "cmp_" + fileName); } @@ -472,7 +484,8 @@ public virtual void SignatureFieldAppearanceTest() { (appearance); // Signing IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(dest, cmp)); NUnit.Framework.Assert.IsNull(new CompareTool().CompareVisually(dest, cmp, DESTINATION_FOLDER, "diff_")); } @@ -505,7 +518,8 @@ private void TestReuseAppearance(String src, String fileName, bool useDeprecated signer.SetReason("Test 1").SetLocation("TestCity").SetSignatureAppearance(new SignatureFieldAppearance(fieldName ).SetContent("New appearance").SetFontColor(ColorConstants.GREEN)); IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); NUnit.Framework.Assert.IsNull(new CompareTool().CompareVisually(dest, cmp, DESTINATION_FOLDER, "diff_")); } @@ -540,7 +554,8 @@ private void TestLayers(String src, String fileName, bool useDeprecated) { } // Signing IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); CompareSignatureAppearances(dest, SOURCE_FOLDER + "cmp_" + fileName); } @@ -557,7 +572,8 @@ private void TestSignatureOnRotatedPage(int pageNum, PdfSignatureAppearance.Rend (SOURCE_FOLDER + "itext.png")).SetPageNumber(pageNum); signer.SetCertificationLevel(PdfSigner.NOT_CERTIFIED); IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); // Make sure iText can open the document new PdfDocument(new PdfReader(dest)).Close(); try { @@ -585,7 +601,8 @@ private void TestSignatureAppearanceAutoscale(String dest, Rectangle rect, PdfSi signer.SetFieldName("Signature1"); // Creating the signature IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); } private static void AssertAppearanceFontSize(String filename, float expectedFontSize) { diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/RSASSAPSSTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/RSASSAPSSTest.cs index 96ba64bb3e..a7f56ac4a3 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/RSASSAPSSTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/RSASSAPSSTest.cs @@ -187,7 +187,7 @@ private void DoSign(String digestAlgo, String signatureAlgo, String outFile, IAp //IExternalSignature pks = new PrivateKeySignature(signPrivateKey, digestAlgo, @params); PdfSigner signer = new PdfSigner(new PdfReader(SOURCE_FILE), fos, new StampingProperties()); signer.SetFieldName(SIGNATURE_FIELD); - signer.SignDetached(pks, signChain, null, null, null, 0, PdfSigner.CryptoStandard.CMS); + signer.SignDetached(new BouncyCastleDigest(), pks, signChain, null, null, null, 0, PdfSigner.CryptoStandard.CMS); } } diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/SequentialSignaturesTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/SequentialSignaturesTest.cs index 84e422ea11..e9dc8b4b45 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/SequentialSignaturesTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/SequentialSignaturesTest.cs @@ -64,7 +64,8 @@ public virtual void SequentialSignOfFileWithAnnots() { signer.SetFieldName(signatureName); signer.GetSignatureAppearance().SetPageRect(new Rectangle(50, 350, 200, 100)).SetReason("Test").SetLocation ("TestCity").SetLayer2Text("Approval test signature.\nCreated by iText."); - signer.SignDetached(pks, signChain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, signChain, null, null, null, 0, PdfSigner.CryptoStandard + .CADES); TestSignUtils.BasicCheckSignedDoc(outFileName, signatureName); NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outFileName, cmpFileName)); } @@ -88,7 +89,8 @@ public virtual void SecondSignOfTaggedDocTest() { appearance.SetPageNumber(1); signer.GetSignatureAppearance().SetPageRect(new Rectangle(50, 550, 200, 100)).SetReason("Test2").SetLocation ("TestCity2").SetLayer2Text("Approval test signature #2.\nCreated by iText."); - signer.SignDetached(pks, signChain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, signChain, null, null, null, 0, PdfSigner.CryptoStandard + .CADES); TestSignUtils.BasicCheckSignedDoc(outFileName, "Signature1"); TestSignUtils.BasicCheckSignedDoc(outFileName, "Signature2"); using (PdfDocument twiceSigned = new PdfDocument(new PdfReader(outFileName))) { 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 5f5635b4ef..50aeb09873 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/SignDeferredTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/SignDeferredTest.cs @@ -216,7 +216,7 @@ internal static byte[] SignDocBytesHash(byte[] docBytesHash, IPrivateKey pk, IX5 } byte[] signatureContent = null; try { - PdfPKCS7 pkcs7 = new PdfPKCS7(null, chain, HASH_ALGORITHM, false); + PdfPKCS7 pkcs7 = new PdfPKCS7(null, chain, HASH_ALGORITHM, new BouncyCastleDigest(), false); byte[] attributes = pkcs7.GetAuthenticatedAttributeBytes(docBytesHash, PdfSigner.CryptoStandard.CMS, null, null); PrivateKeySignature signature = new PrivateKeySignature(pk, HASH_ALGORITHM); diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/SignedAppearanceTextTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/SignedAppearanceTextTest.cs index a204195c93..afb28b8770 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/SignedAppearanceTextTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/SignedAppearanceTextTest.cs @@ -263,7 +263,8 @@ protected internal virtual void Sign(String src, String name, String dest, Strin } // Creating the signature IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); } private static IDictionary> GetTestMap(Rectangle ignoredArea) { diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/SimpleSigningTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/SimpleSigningTest.cs index c61d1aee6c..d8127b9885 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/SimpleSigningTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/SimpleSigningTest.cs @@ -119,7 +119,8 @@ public virtual void SignWithTempFileTest() { CreateAppearance(signer, "Test 1", "TestCity", false, rect, 12f); // Creating the signature IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); - signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES + ); NUnit.Framework.Assert.IsNull(new CompareTool().CompareVisually(outPdf, cmpPdf, DESTINATION_FOLDER, "diff_" , GetTestMap(rect))); NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outPdf, cmpPdf)); @@ -141,7 +142,7 @@ protected internal virtual void Sign(String src, String name, String dest, IX509 CreateAppearance(signer, reason, location, setReuseAppearance, rectangleForNewField, fontSize); // Creating the signature IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm); - signer.SignDetached(pks, chain, null, null, null, 0, subfilter); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, subfilter); } private static IDictionary> GetTestMap(Rectangle ignoredArea) { diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/TaggedPdfSigningTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/TaggedPdfSigningTest.cs index b066d05a13..247c6ed889 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/TaggedPdfSigningTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/TaggedPdfSigningTest.cs @@ -122,7 +122,7 @@ protected internal virtual void Sign(String src, String name, String dest, IX509 signer.SetFieldName(name); // Creating the signature IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm); - signer.SignDetached(pks, chain, null, null, null, 0, subfilter); + signer.SignDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, subfilter); } private static IDictionary> GetTestMap(Rectangle ignoredArea) { 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 4fe52119fb..b64562c30e 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/TwoPhaseSigningTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/TwoPhaseSigningTest.cs @@ -24,11 +24,11 @@ You should have received a copy of the GNU Affero General Public License using System.IO; using System.Security.Cryptography; using System.Xml.Serialization; -using Org.BouncyCastle.Asn1; using iText.Bouncycastleconnector; using iText.Commons.Bouncycastle; using iText.Commons.Bouncycastle.Cert; using iText.Commons.Bouncycastle.Crypto; +using iText.Commons.Digest; using iText.Commons.Utils; using iText.IO.Source; using iText.Kernel.Exceptions; @@ -37,7 +37,6 @@ You should have received a copy of the GNU Affero General Public License using iText.Signatures.Exceptions; using iText.Signatures.Testutils; using iText.Test; -using AlgorithmIdentifier = Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier; using SignerInfo = iText.Signatures.Cms.SignerInfo; namespace iText.Signatures.Sign { @@ -280,7 +279,7 @@ public virtual void TestWithCMS() { } private byte[] SignDigest(byte[] data, String hashAlgorithm) { - PdfPKCS7 sgn = new PdfPKCS7((IPrivateKey)null, chain, hashAlgorithm, false); + PdfPKCS7 sgn = new PdfPKCS7((IPrivateKey)null, chain, hashAlgorithm, new BouncyCastleDigest(), false); byte[] sh = sgn.GetAuthenticatedAttributeBytes(data, PdfSigner.CryptoStandard.CMS, null, null); PrivateKeySignature pkSign = new PrivateKeySignature(pk, hashAlgorithm); byte[] signData = pkSign.Sign(sh); @@ -314,7 +313,7 @@ private byte[] PrepareDocumentAndCMS(FileInfo document, ByteArrayOutputStream pr cms.AddCertificates(chain); byte[] signedAttributesToSign = cms.GetSerializedSignedAttributes(); - IDigest sha = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest(DIGEST_ALGORITHM + IMessageDigest sha = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest(DIGEST_ALGORITHM ); byte[] dataToSign = sha.Digest(signedAttributesToSign); diff --git a/itext.tests/itext.sign.tests/itext/signatures/testutils/SignTestPortUtil.cs b/itext.tests/itext.sign.tests/itext/signatures/testutils/SignTestPortUtil.cs index 075ef52611..41b2c45dff 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/testutils/SignTestPortUtil.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/testutils/SignTestPortUtil.cs @@ -32,6 +32,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Bouncycastle.Crypto; using iText.Commons.Bouncycastle.Crypto.Generators; using iText.Commons.Bouncycastle.Math; +using iText.Commons.Digest; using iText.Kernel.Pdf; namespace iText.Signatures.Testutils { diff --git a/itext.tests/itext.sign.tests/itext/signatures/testutils/client/TestTsaClient.cs b/itext.tests/itext.sign.tests/itext/signatures/testutils/client/TestTsaClient.cs index dd46f38c70..7d21547297 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/testutils/client/TestTsaClient.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/testutils/client/TestTsaClient.cs @@ -28,6 +28,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Bouncycastle.Crypto; using iText.Commons.Bouncycastle.Math; using iText.Commons.Bouncycastle.Tsp; +using iText.Commons.Digest; using iText.Commons.Utils; using iText.Signatures; using iText.Signatures.Testutils; @@ -54,7 +55,7 @@ public virtual int GetTokenSizeEstimate() { } public virtual IDigest GetMessageDigest() { - return SignTestPortUtil.GetMessageDigest(DIGEST_ALG); + return (IDigest)SignTestPortUtil.GetMessageDigest(DIGEST_ALG); } public virtual byte[] GetTimeStampToken(byte[] imprint) { diff --git a/itext/itext.bouncy-castle-adapter/itext/bouncycastle/BouncyCastleFactory.cs b/itext/itext.bouncy-castle-adapter/itext/bouncycastle/BouncyCastleFactory.cs index 2155a77548..3c8fb4830b 100644 --- a/itext/itext.bouncy-castle-adapter/itext/bouncycastle/BouncyCastleFactory.cs +++ b/itext/itext.bouncy-castle-adapter/itext/bouncycastle/BouncyCastleFactory.cs @@ -948,7 +948,11 @@ public ICollection CreateX509Crls(Stream input) { /// public IDigest CreateIDigest(string hashAlgorithm) { - return new DigestBC(DigestUtilities.GetDigest(hashAlgorithm)); + try { + return new DigestBC(DigestUtilities.GetDigest(hashAlgorithm)); + } catch (SecurityUtilityException e) { + throw new SecurityUtilityExceptionBC(e); + } } /// diff --git a/itext/itext.bouncy-castle-adapter/itext/bouncycastle/security/SecurityUtilityExceptionBC.cs b/itext/itext.bouncy-castle-adapter/itext/bouncycastle/security/SecurityUtilityExceptionBC.cs new file mode 100644 index 0000000000..89580cefee --- /dev/null +++ b/itext/itext.bouncy-castle-adapter/itext/bouncycastle/security/SecurityUtilityExceptionBC.cs @@ -0,0 +1,82 @@ +/* + 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 iText.Commons.Bouncycastle.Security; +using iText.Commons.Utils; +using Org.BouncyCastle.Security; + +namespace iText.Bouncycastle.Security { + /// Wrapper class for . + public class SecurityUtilityExceptionBC : AbstractSecurityUtilityException { + private readonly SecurityUtilityException exception; + /// + /// Creates new wrapper for . + /// + /// + /// to be wrapped + /// + public SecurityUtilityExceptionBC(SecurityUtilityException exception) { + this.exception = exception; + } + + /// Get actual org.bouncycastle object being wrapped. + /// wrapped . + public SecurityUtilityException GetException() { + return exception; + } + + /// Indicates whether some other object is "equal to" this one. + /// Indicates whether some other object is "equal to" this one. Compares wrapped objects. + public override bool Equals(Object o) { + if (this == o) { + return true; + } + if (o == null || GetType() != o.GetType()) { + return false; + } + SecurityUtilityExceptionBC that = (SecurityUtilityExceptionBC) o; + return Object.Equals(exception, that.exception); + } + + /// Returns a hash code value based on the wrapped object. + public override int GetHashCode() { + return JavaUtil.ArraysHashCode(exception); + } + + /// + /// Delegates + /// toString + /// method call to the wrapped object. + /// + public override String ToString() { + return exception.ToString(); + } + + /// + /// Delegates + /// getMessage + /// method call to the wrapped exception. + /// + public override String Message => exception.Message; + } +} \ No newline at end of file diff --git a/itext/itext.bouncy-castle-fips-adapter/itext/bouncycastlefips/BouncyCastleFipsFactory.cs b/itext/itext.bouncy-castle-fips-adapter/itext/bouncycastlefips/BouncyCastleFipsFactory.cs index cbab7eee33..d7e0202e75 100644 --- a/itext/itext.bouncy-castle-fips-adapter/itext/bouncycastlefips/BouncyCastleFipsFactory.cs +++ b/itext/itext.bouncy-castle-fips-adapter/itext/bouncycastlefips/BouncyCastleFipsFactory.cs @@ -83,7 +83,6 @@ You should have received a copy of the GNU Affero General Public License using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Asymmetric; using Org.BouncyCastle.Crypto.Fips; -using Org.BouncyCastle.Ocsp; using Org.BouncyCastle.OpenSsl; using Org.BouncyCastle.Operators; using Org.BouncyCastle.Operators.Utilities; diff --git a/itext/itext.bouncy-castle-fips-adapter/itext/bouncycastlefips/crypto/DigestBCFips.cs b/itext/itext.bouncy-castle-fips-adapter/itext/bouncycastlefips/crypto/DigestBCFips.cs index 7497738f30..78d9b1a21b 100644 --- a/itext/itext.bouncy-castle-fips-adapter/itext/bouncycastlefips/crypto/DigestBCFips.cs +++ b/itext/itext.bouncy-castle-fips-adapter/itext/bouncycastlefips/crypto/DigestBCFips.cs @@ -60,6 +60,8 @@ public DigestBCFips(IStreamCalculator iDigest) { /// hash algorithm to create IStreamCalculator /// public DigestBCFips(string hashAlgorithm) { + if (hashAlgorithm == null) + throw new ArgumentNullException(nameof(hashAlgorithm)); if ("MD5".Equals(hashAlgorithm)) { md5 = System.Security.Cryptography.MD5.Create(); algorithmName = "MD5"; diff --git a/itext/itext.commons/itext/commons/bouncycastle/crypto/IDigest.cs b/itext/itext.commons/itext/commons/bouncycastle/crypto/IDigest.cs index 1fc53cdbd4..16eeff2629 100644 --- a/itext/itext.commons/itext/commons/bouncycastle/crypto/IDigest.cs +++ b/itext/itext.commons/itext/commons/bouncycastle/crypto/IDigest.cs @@ -20,12 +20,15 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ + +using iText.Commons.Digest; + namespace iText.Commons.Bouncycastle.Crypto { /// /// This interface represents the wrapper for IDigest that provides the ability /// to switch between bouncy-castle and bouncy-castle FIPS implementations. /// - public interface IDigest { + public interface IDigest : IMessageDigest { /// /// Calls actual /// Digest diff --git a/itext/itext.commons/itext/commons/bouncycastle/security/AbstractSecurityUtilityException.cs b/itext/itext.commons/itext/commons/bouncycastle/security/AbstractSecurityUtilityException.cs new file mode 100644 index 0000000000..8b481448dc --- /dev/null +++ b/itext/itext.commons/itext/commons/bouncycastle/security/AbstractSecurityUtilityException.cs @@ -0,0 +1,45 @@ +/* + 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; + +namespace iText.Commons.Bouncycastle.Security { + /// + /// This class represents the wrapper for SecurityUtilityException that provides the ability + /// to switch between bouncy-castle and bouncy-castle FIPS implementations. + /// + public class AbstractSecurityUtilityException : Exception { + /// + /// Base constructor for . + /// + protected AbstractSecurityUtilityException() { + } + + /// + /// Creates new wrapper instance for . + /// The abstract class constructor gets executed from a derived class. + /// + /// Exception message + protected AbstractSecurityUtilityException(string message) : base(message) { + } + } +} diff --git a/itext/itext.commons/itext/commons/digest/IMessageDigest.cs b/itext/itext.commons/itext/commons/digest/IMessageDigest.cs new file mode 100644 index 0000000000..b06ed79b1e --- /dev/null +++ b/itext/itext.commons/itext/commons/digest/IMessageDigest.cs @@ -0,0 +1,72 @@ +/* + 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 . + */ +namespace iText.Commons.Digest { + /// + /// This interface should be implemented to provide applications the functionality of a message digest algorithm. + /// + public interface IMessageDigest { + /// + /// Performs a final update on the digest using the specified array of bytes, + /// then completes the digest computation. + /// + /// the input to be updated before the digest is completed + /// The array of bytes for the resulting hash value + byte[] Digest(byte[] enc); + + /// + /// Completes the hash computation by performing final operations such as padding. + /// Leaves the digest reset. + /// + /// The array of bytes for the resulting hash value + byte[] Digest(); + + /// + /// Gets byte length of wrapped digest algorithm. + /// + /// The length of the digest in bytes. + int GetDigestLength(); + + /// + /// Updates the digest using the specified array of bytes, starting at the specified offset. + /// + /// byte array buffer + /// the offset to start from in the array of bytes + /// the number of bytes to use, starting at offset + void Update(byte[] buf, int off, int len); + + /// + /// Updates the digest using the specified array of bytes. + /// + /// byte array buffer + void Update(byte[] buf); + + /// Resets the digest for further use. + void Reset(); + + /// + /// Returns a string that identifies the algorithm, independent of implementation details. + /// + /// The name of the algorithm. + string GetAlgorithmName(); + } +} \ No newline at end of file diff --git a/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubKeySecurityHandler.cs b/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubKeySecurityHandler.cs index 6483828d14..9344d8eabf 100644 --- a/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubKeySecurityHandler.cs +++ b/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubKeySecurityHandler.cs @@ -31,6 +31,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Bouncycastle.Cert; using iText.Commons.Bouncycastle.Crypto; using iText.Commons.Bouncycastle.Security; +using iText.Commons.Digest; using iText.IO.Util; using iText.Kernel.Crypto; using iText.Kernel.Exceptions; @@ -55,7 +56,7 @@ protected internal PubKeySecurityHandler() { } protected internal virtual byte[] ComputeGlobalKey(String messageDigestAlgorithm, bool encryptMetadata) { - IDigest md; + IMessageDigest md; byte[] encodedRecipient; try { md = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest(messageDigestAlgorithm @@ -87,7 +88,7 @@ protected internal static byte[] ComputeGlobalKeyOnReading(PdfDictionary encrypt } byte[] envelopedData = EncryptionUtils.FetchEnvelopedData(certificateKey, certificate, recipients); byte[] encryptionKey; - IDigest md; + IMessageDigest md; try { md = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest(digestAlgorithm); md.Update(envelopedData, 0, 20); diff --git a/itext/itext.kernel/itext/kernel/crypto/securityhandler/SecurityHandler.cs b/itext/itext.kernel/itext/kernel/crypto/securityhandler/SecurityHandler.cs index b74c0f6524..2eb4a8cc7b 100644 --- a/itext/itext.kernel/itext/kernel/crypto/securityhandler/SecurityHandler.cs +++ b/itext/itext.kernel/itext/kernel/crypto/securityhandler/SecurityHandler.cs @@ -27,7 +27,6 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons; using iText.Commons.Bouncycastle; using iText.Commons.Bouncycastle.Crypto; -using iText.Kernel.Crypto; using iText.Kernel.Exceptions; using iText.Kernel.Logs; diff --git a/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardHandlerUsingAes256.cs b/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardHandlerUsingAes256.cs index c46f5d4052..51143e15e2 100644 --- a/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardHandlerUsingAes256.cs +++ b/itext/itext.kernel/itext/kernel/crypto/securityhandler/StandardHandlerUsingAes256.cs @@ -24,8 +24,8 @@ You should have received a copy of the GNU Affero General Public License using System.IO; using Microsoft.Extensions.Logging; using iText.Commons; -using iText.Commons.Bouncycastle.Crypto; using iText.Commons.Bouncycastle.Math; +using iText.Commons.Digest; using iText.Commons.Utils; using iText.IO.Util; using iText.Kernel.Crypto; @@ -243,8 +243,8 @@ private byte[] ComputeHash(byte[] password, byte[] salt, int saltOffset, int sal } private byte[] ComputeHash(byte[] password, byte[] salt, int saltOffset, int saltLen, byte[] userKey) { - IDigest mdSha256 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest("SHA-256" - ); + IMessageDigest mdSha256 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest + ("SHA-256"); mdSha256.Update(password); mdSha256.Update(salt, saltOffset, saltLen); if (userKey != null) { @@ -253,10 +253,10 @@ private byte[] ComputeHash(byte[] password, byte[] salt, int saltOffset, int sal byte[] k = mdSha256.Digest(); if (isPdf2) { // See 7.6.4.3.3 "Algorithm 2.B" - IDigest mdSha384 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest("SHA-384" - ); - IDigest mdSha512 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest("SHA-512" - ); + IMessageDigest mdSha384 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest + ("SHA-384"); + IMessageDigest mdSha512 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest + ("SHA-512"); int userKeyLen = userKey != null ? userKey.Length : 0; int passAndUserKeyLen = password.Length + userKeyLen; // k1 repetition length @@ -279,7 +279,7 @@ private byte[] ComputeHash(byte[] password, byte[] salt, int saltOffset, int sal (k, 16, 32)); byte[] e = cipher.ProcessBlock(k1, 0, k1.Length); // c) - IDigest md = null; + IMessageDigest md = null; IBigInteger i_1 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateBigInteger(1, JavaUtil.ArraysCopyOf(e, 16)); int remainder = i_1.Remainder(iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateBigInteger().ValueOf diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfEncryption.cs b/itext/itext.kernel/itext/kernel/pdf/PdfEncryption.cs index a6dd9d4844..fe15fdd153 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfEncryption.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfEncryption.cs @@ -24,6 +24,7 @@ You should have received a copy of the GNU Affero General Public License using System.IO; using iText.Commons.Bouncycastle.Cert; using iText.Commons.Bouncycastle.Crypto; +using iText.Commons.Digest; using iText.Commons.Utils; using iText.IO.Source; using iText.Kernel.Crypto; @@ -328,7 +329,7 @@ public PdfEncryption(PdfDictionary pdfDict, IPrivateKey certificateKey, IX509Cer } public static byte[] GenerateNewDocumentId() { - IDigest sha512; + IMessageDigest sha512; try { sha512 = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest("SHA-512"); } diff --git a/itext/itext.kernel/itext/kernel/pdf/SmartModePdfObjectsSerializer.cs b/itext/itext.kernel/itext/kernel/pdf/SmartModePdfObjectsSerializer.cs index f05f6fe622..cba3b1bcb8 100644 --- a/itext/itext.kernel/itext/kernel/pdf/SmartModePdfObjectsSerializer.cs +++ b/itext/itext.kernel/itext/kernel/pdf/SmartModePdfObjectsSerializer.cs @@ -22,13 +22,13 @@ You should have received a copy of the GNU Affero General Public License */ using System; using System.Collections.Generic; -using iText.Commons.Bouncycastle.Crypto; +using iText.Commons.Digest; using iText.IO.Source; using iText.Kernel.Exceptions; namespace iText.Kernel.Pdf { internal class SmartModePdfObjectsSerializer { - private IDigest sha512; + private IMessageDigest sha512; private Dictionary serializedContentToObj = new Dictionary< SerializedObjectContent, PdfIndirectReference>(); diff --git a/itext/itext.sign/itext/signatures/BouncyCastleDigest.cs b/itext/itext.sign/itext/signatures/BouncyCastleDigest.cs new file mode 100644 index 0000000000..9e9c535865 --- /dev/null +++ b/itext/itext.sign/itext/signatures/BouncyCastleDigest.cs @@ -0,0 +1,39 @@ +/* + 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 iText.Bouncycastleconnector; +using iText.Commons.Bouncycastle; +using iText.Commons.Digest; + +namespace iText.Signatures { + /// + /// Implementation for digests accessed directly from the BouncyCastle library. + /// + public class BouncyCastleDigest : IExternalDigest { + private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory(); + + /// + public IMessageDigest GetMessageDigest(string hashAlgorithm) { + return FACTORY.CreateIDigest(hashAlgorithm); + } + } +} \ No newline at end of file diff --git a/itext/itext.sign/itext/signatures/DigestAlgorithms.cs b/itext/itext.sign/itext/signatures/DigestAlgorithms.cs index 5f403cf139..7316c1f7ee 100644 --- a/itext/itext.sign/itext/signatures/DigestAlgorithms.cs +++ b/itext/itext.sign/itext/signatures/DigestAlgorithms.cs @@ -28,6 +28,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons; using iText.Commons.Bouncycastle; using iText.Commons.Bouncycastle.Crypto; +using iText.Commons.Digest; using iText.Signatures.Exceptions; using iText.Signatures.Logs; @@ -197,7 +198,7 @@ public static IDigest GetMessageDigestFromOid(String digestOid) { /// the algorithm you want to use to create a hash /// a MessageDigest object public static IDigest GetMessageDigest(String hashAlgorithm) { - return SignUtils.GetMessageDigest(hashAlgorithm); + return (IDigest)SignUtils.GetMessageDigest(hashAlgorithm); } /// Creates a hash using a specific digest algorithm and a provider. @@ -222,6 +223,21 @@ public static byte[] Digest(Stream data, IDigest messageDigest) { return messageDigest.Digest(); } + /// Create a digest based on the inputstream. + /// data to be digested + /// algorithm to be used + /// external digest to be used + /// digest of the data + public static byte[] Digest(Stream data, String hashAlgorithm, IExternalDigest externalDigest) { + byte[] buf = new byte[8192]; + int n; + IMessageDigest messageDigest = SignUtils.GetMessageDigest(hashAlgorithm, externalDigest); + while ((n = data.Read(buf)) > 0) { + messageDigest.Update(buf, 0, n); + } + return messageDigest.Digest(); + } + /// Gets the digest name for a certain id. /// an id (for instance "1.2.840.113549.2.5") /// a digest name (for instance "MD5") diff --git a/itext/itext.sign/itext/signatures/IExternalDigest.cs b/itext/itext.sign/itext/signatures/IExternalDigest.cs new file mode 100644 index 0000000000..6b551c8b33 --- /dev/null +++ b/itext/itext.sign/itext/signatures/IExternalDigest.cs @@ -0,0 +1,39 @@ +/* +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 iText.Commons.Digest; + +namespace iText.Signatures { + /// + /// ExternalDigest allows the use of implementations of + /// + /// other than + /// . + /// + public interface IExternalDigest { + /// Returns the MessageDigest associated with the provided hashing algorithm. + /// String value representing the hashing algorithm + /// MessageDigest MessageDigest object + IMessageDigest GetMessageDigest(String hashAlgorithm); + } +} diff --git a/itext/itext.sign/itext/signatures/ITSAClient.cs b/itext/itext.sign/itext/signatures/ITSAClient.cs index 9a35d842b9..017a9eff5e 100644 --- a/itext/itext.sign/itext/signatures/ITSAClient.cs +++ b/itext/itext.sign/itext/signatures/ITSAClient.cs @@ -47,12 +47,12 @@ public interface ITSAClient { /// /// Returns the - /// + /// /// to digest the data imprint /// /// /// The - /// + /// /// object. /// IDigest GetMessageDigest(); diff --git a/itext/itext.sign/itext/signatures/LtvVerification.cs b/itext/itext.sign/itext/signatures/LtvVerification.cs index d90c32b929..c625d65dee 100644 --- a/itext/itext.sign/itext/signatures/LtvVerification.cs +++ b/itext/itext.sign/itext/signatures/LtvVerification.cs @@ -31,8 +31,8 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Bouncycastle.Asn1.Ocsp; using iText.Commons.Bouncycastle.Cert; using iText.Commons.Bouncycastle.Cert.Ocsp; -using iText.Commons.Bouncycastle.Crypto; using iText.Commons.Bouncycastle.Operator; +using iText.Commons.Digest; using iText.Commons.Utils; using iText.IO.Font; using iText.IO.Source; @@ -432,7 +432,8 @@ private PdfName GetSignatureHashKey(String signatureName) { } private static byte[] HashBytesSha1(byte[] b) { - IDigest sh = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest("SHA1"); + IMessageDigest sh = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest("SHA1" + ); return sh.Digest(b); } diff --git a/itext/itext.sign/itext/signatures/PKCS7ExternalSignatureContainer.cs b/itext/itext.sign/itext/signatures/PKCS7ExternalSignatureContainer.cs index 192286ccf0..b9a2c07ff3 100644 --- a/itext/itext.sign/itext/signatures/PKCS7ExternalSignatureContainer.cs +++ b/itext/itext.sign/itext/signatures/PKCS7ExternalSignatureContainer.cs @@ -58,7 +58,7 @@ public PKCS7ExternalSignatureContainer(IPrivateKey privateKey, IX509Certificate[ } public virtual byte[] Sign(Stream data) { - PdfPKCS7 sgn = new PdfPKCS7((IPrivateKey)null, chain, hashAlgorithm, false); + PdfPKCS7 sgn = new PdfPKCS7((IPrivateKey)null, chain, hashAlgorithm, new BouncyCastleDigest(), false); if (signaturePolicy != null) { sgn.SetSignaturePolicy(signaturePolicy); } diff --git a/itext/itext.sign/itext/signatures/PadesTwoPhaseSigningHelper.cs b/itext/itext.sign/itext/signatures/PadesTwoPhaseSigningHelper.cs index f0e3a59bab..ca9d9ce73f 100644 --- a/itext/itext.sign/itext/signatures/PadesTwoPhaseSigningHelper.cs +++ b/itext/itext.sign/itext/signatures/PadesTwoPhaseSigningHelper.cs @@ -27,7 +27,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Bouncycastle; using iText.Commons.Bouncycastle.Asn1; using iText.Commons.Bouncycastle.Cert; -using iText.Commons.Bouncycastle.Crypto; +using iText.Commons.Digest; using iText.Commons.Utils; using iText.Kernel.Exceptions; using iText.Kernel.Pdf; @@ -334,8 +334,8 @@ public virtual CMSContainer CreateCMSContainerWithoutSignature(IX509Certificate[ signerInfo.SetDigestAlgorithm(new AlgorithmIdentifier(digestAlgorithmOid)); cms.AddCertificates(x509FullChain); cms.SetSignerInfo(signerInfo); - IDigest messageDigest = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest( - DigestAlgorithms.GetDigest(digestAlgorithmOid)); + IMessageDigest messageDigest = iText.Bouncycastleconnector.BouncyCastleFactoryCreator.GetFactory().CreateIDigest + (DigestAlgorithms.GetDigest(digestAlgorithmOid)); int realSignatureSize = messageDigest.GetDigestLength() + (int)cms.GetSizeEstimation(); if (tsaClient != null) { realSignatureSize += tsaClient.GetTokenSizeEstimate(); diff --git a/itext/itext.sign/itext/signatures/PdfPKCS7.cs b/itext/itext.sign/itext/signatures/PdfPKCS7.cs index 90a3185da8..c12656f68c 100644 --- a/itext/itext.sign/itext/signatures/PdfPKCS7.cs +++ b/itext/itext.sign/itext/signatures/PdfPKCS7.cs @@ -39,6 +39,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Bouncycastle.Cert.Ocsp; using iText.Commons.Bouncycastle.Crypto; using iText.Commons.Bouncycastle.Math; +using iText.Commons.Digest; using iText.Commons.Utils; using iText.Kernel.Exceptions; using iText.Kernel.Pdf; @@ -81,8 +82,9 @@ public class PdfPKCS7 { /// the hash algorithm /// the provider or null for the default provider /// true if the sub-filter is adbe.pkcs7.sha1 - public PdfPKCS7(IPrivateKey privKey, IX509Certificate[] certChain, String hashAlgorithm, bool hasEncapContent - ) { + public PdfPKCS7(IPrivateKey privKey, IX509Certificate[] certChain, String hashAlgorithm, IExternalDigest interfaceDigest + , bool hasEncapContent) { + this.interfaceDigest = interfaceDigest; // message digest digestAlgorithmOid = DigestAlgorithms.GetAllowedDigest(hashAlgorithm); if (digestAlgorithmOid == null) { @@ -117,6 +119,17 @@ public PdfPKCS7(IPrivateKey privKey, IX509Certificate[] certChain, String hashAl } } + /// Assembles all the elements needed to create a signature, except for the data. + /// the private key + /// the certificate chain + /// the hash algorithm + /// the provider or null for the default provider + /// true if the sub-filter is adbe.pkcs7.sha1 + public PdfPKCS7(IPrivateKey privKey, IX509Certificate[] certChain, String hashAlgorithm, bool hasEncapContent + ) + : this(privKey, certChain, hashAlgorithm, new BouncyCastleDigest(), hasEncapContent) { + } + // Constructors for validating existing signatures /// Use this constructor if you want to verify a signature using the sub-filter adbe.x509.rsa_sha1. /// the /Contents key @@ -281,7 +294,7 @@ public PdfPKCS7(byte[] contentsKey, PdfName filterSubtype) { IEssCertID[] cerv2m = sv2.GetCerts(); IEssCertID cerv2 = cerv2m[0]; byte[] enc2 = signCert.GetEncoded(); - IDigest m2 = SignUtils.GetMessageDigest("SHA-1"); + IMessageDigest m2 = SignUtils.GetMessageDigest("SHA-1"); byte[] signCertHash = m2.Digest(enc2); byte[] hs2 = cerv2.GetCertHash(); if (!JavaUtil.ArraysEquals(signCertHash, hs2)) { @@ -298,7 +311,7 @@ public PdfPKCS7(byte[] contentsKey, PdfName filterSubtype) { IEssCertIDv2 cerv2 = cerv2m[0]; IAlgorithmIdentifier ai2 = cerv2.GetHashAlgorithm(); byte[] enc2 = signCert.GetEncoded(); - IDigest m2 = SignUtils.GetMessageDigest(DigestAlgorithms.GetDigest(ai2.GetAlgorithm().GetId())); + IMessageDigest m2 = SignUtils.GetMessageDigest(DigestAlgorithms.GetDigest(ai2.GetAlgorithm().GetId())); byte[] signCertHash = m2.Digest(enc2); byte[] hs2 = cerv2.GetCertHash(); if (!JavaUtil.ArraysEquals(signCertHash, hs2)) { @@ -457,7 +470,7 @@ public virtual int GetSigningInfoVersion() { private readonly String digestAlgorithmOid; /// The object that will create the digest - private IDigest messageDigest; + private IMessageDigest messageDigest; /// The digest algorithms private ICollection digestalgos; @@ -561,6 +574,8 @@ public virtual String GetSignatureAlgorithmName() { /* * DIGITAL SIGNATURE CREATION */ + private IExternalDigest interfaceDigest; + // The signature is created externally /// The signature value or signed digest, if created outside this class private byte[] externalSignatureValue; @@ -1045,7 +1060,7 @@ private IDerSet GetAuthenticatedAttributeSet(byte[] secondDigest, ICollectionencrypted digest - private IDigest encContDigest; + private IMessageDigest encContDigest; // Stefan Santesson /// Indicates if a signature has already been verified diff --git a/itext/itext.sign/itext/signatures/PdfPadesSigner.cs b/itext/itext.sign/itext/signatures/PdfPadesSigner.cs index e7f482c301..b4fd535e3b 100644 --- a/itext/itext.sign/itext/signatures/PdfPadesSigner.cs +++ b/itext/itext.sign/itext/signatures/PdfPadesSigner.cs @@ -57,6 +57,8 @@ public class PdfPadesSigner { private String temporaryDirectoryPath = null; + private IExternalDigest externalDigest = new BouncyCastleDigest(); + private StampingProperties stampingProperties = new StampingProperties().UseAppendMode(); private MemoryStream tempOutputStream; @@ -490,6 +492,34 @@ public virtual iText.Signatures.PdfPadesSigner SetCrlClient(ICrlClient crlClient return this; } + /// + /// Set + /// + /// to be used for main signing operation. + /// + /// + /// Set + /// + /// to be used for main signing operation. + /// + /// If none is set, + /// + /// instance will be used instead. + /// + /// + /// + /// + /// to be used for main signing operation. + /// + /// + /// same instance of + /// + /// + public virtual iText.Signatures.PdfPadesSigner SetExternalDigest(IExternalDigest externalDigest) { + this.externalDigest = externalDigest; + return this; + } + /// /// Set /// @@ -606,7 +636,7 @@ private void PerformSignDetached(SignerProperties signerProperties, bool isFinal IX509Certificate[] fullChain = issuingCertificateRetriever.RetrieveMissingCertificates(chain); PdfSigner signer = CreatePdfSigner(signerProperties, isFinal); try { - signer.SignDetached(externalSignature, fullChain, null, null, tsaClient, estimatedSize, PdfSigner.CryptoStandard + signer.SignDetached(externalDigest, externalSignature, fullChain, null, null, tsaClient, estimatedSize, PdfSigner.CryptoStandard .CADES); } finally { diff --git a/itext/itext.sign/itext/signatures/PdfSigner.cs b/itext/itext.sign/itext/signatures/PdfSigner.cs index 702ee1f4eb..56f9a0cf64 100644 --- a/itext/itext.sign/itext/signatures/PdfSigner.cs +++ b/itext/itext.sign/itext/signatures/PdfSigner.cs @@ -26,6 +26,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Bouncycastle.Asn1.Esf; using iText.Commons.Bouncycastle.Cert; using iText.Commons.Bouncycastle.Crypto; +using iText.Commons.Digest; using iText.Commons.Utils; using iText.Forms; using iText.Forms.Fields; @@ -556,6 +557,28 @@ public virtual PdfSignatureFormField GetSignatureField() { return null; } + /// Signs the document using the detached mode, CMS or CAdES equivalent. + /// + /// Signs the document using the detached mode, CMS or CAdES equivalent. + ///

+ /// NOTE: This method closes the underlying pdf document. This means, that current instance + /// of PdfSigner cannot be used after this method call. + ///
+ /// the interface providing the actual signing + /// the certificate chain + /// the CRL list + /// the OCSP client + /// the Timestamp client + /// an implementation that provides the digest + /// the reserved size for the signature. It will be estimated if 0 + /// Either Signature.CMS or Signature.CADES + public virtual void SignDetached(IExternalDigest externalDigest, IExternalSignature externalSignature, IX509Certificate + [] chain, ICollection crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize + , PdfSigner.CryptoStandard sigtype) { + SignDetached(externalDigest, externalSignature, chain, crlList, ocspClient, tsaClient, estimatedSize, sigtype + , (ISignaturePolicyIdentifier)null); + } + /// Signs the document using the detached mode, CMS or CAdES equivalent. /// /// Signs the document using the detached mode, CMS or CAdES equivalent. @@ -573,8 +596,31 @@ public virtual PdfSignatureFormField GetSignatureField() { public virtual void SignDetached(IExternalSignature externalSignature, IX509Certificate[] chain, ICollection crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize, PdfSigner.CryptoStandard sigtype) { - SignDetached(externalSignature, chain, crlList, ocspClient, tsaClient, estimatedSize, sigtype, (ISignaturePolicyIdentifier - )null); + SignDetached(new BouncyCastleDigest(), externalSignature, chain, crlList, ocspClient, tsaClient, estimatedSize + , sigtype, (ISignaturePolicyIdentifier)null); + } + + /// Signs the document using the detached mode, CMS or CAdES equivalent. + /// + /// Signs the document using the detached mode, CMS or CAdES equivalent. + ///

+ /// NOTE: This method closes the underlying pdf document. This means, that current instance + /// of PdfSigner cannot be used after this method call. + ///
+ /// the interface providing the actual signing + /// the certificate chain + /// the CRL list + /// the OCSP client + /// the Timestamp client + /// an implementation that provides the digest + /// the reserved size for the signature. It will be estimated if 0 + /// Either Signature.CMS or Signature.CADES + /// the signature policy (for EPES signatures) + public virtual void SignDetached(IExternalDigest externalDigest, IExternalSignature externalSignature, IX509Certificate + [] chain, ICollection crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize + , PdfSigner.CryptoStandard sigtype, SignaturePolicyInfo signaturePolicy) { + SignDetached(externalDigest, externalSignature, chain, crlList, ocspClient, tsaClient, estimatedSize, sigtype + , signaturePolicy.ToSignaturePolicyIdentifier()); } /// Signs the document using the detached mode, CMS or CAdES equivalent. @@ -595,8 +641,8 @@ public virtual void SignDetached(IExternalSignature externalSignature, IX509Cert public virtual void SignDetached(IExternalSignature externalSignature, IX509Certificate[] chain, ICollection crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize, PdfSigner.CryptoStandard sigtype, SignaturePolicyInfo signaturePolicy) { - SignDetached(externalSignature, chain, crlList, ocspClient, tsaClient, estimatedSize, sigtype, signaturePolicy - .ToSignaturePolicyIdentifier()); + SignDetached(new BouncyCastleDigest(), externalSignature, chain, crlList, ocspClient, tsaClient, estimatedSize + , sigtype, signaturePolicy); } /// Signs the document using the detached mode, CMS or CAdES equivalent. @@ -617,6 +663,29 @@ public virtual void SignDetached(IExternalSignature externalSignature, IX509Cert public virtual void SignDetached(IExternalSignature externalSignature, IX509Certificate[] chain, ICollection crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize, PdfSigner.CryptoStandard sigtype, ISignaturePolicyIdentifier signaturePolicy) { + SignDetached(new BouncyCastleDigest(), externalSignature, chain, crlList, ocspClient, tsaClient, estimatedSize + , sigtype, signaturePolicy); + } + + /// Signs the document using the detached mode, CMS or CAdES equivalent. + /// + /// Signs the document using the detached mode, CMS or CAdES equivalent. + ///

+ /// NOTE: This method closes the underlying pdf document. This means, that current instance + /// of PdfSigner cannot be used after this method call. + ///
+ /// the interface providing the actual signing + /// the certificate chain + /// the CRL list + /// the OCSP client + /// the Timestamp client + /// an implementation that provides the digest + /// the reserved size for the signature. It will be estimated if 0 + /// Either Signature.CMS or Signature.CADES + /// the signature policy (for EPES signatures) + public virtual void SignDetached(IExternalDigest externalDigest, IExternalSignature externalSignature, IX509Certificate + [] chain, ICollection crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize + , PdfSigner.CryptoStandard sigtype, ISignaturePolicyIdentifier signaturePolicy) { if (closed) { throw new PdfException(SignExceptionMessageConstant.THIS_INSTANCE_OF_PDF_SIGNER_ALREADY_CLOSED); } @@ -672,12 +741,12 @@ public virtual void SignDetached(IExternalSignature externalSignature, IX509Cert IDictionary exc = new Dictionary(); exc.Put(PdfName.Contents, estimatedSize * 2 + 2); PreClose(exc); - PdfPKCS7 sgn = new PdfPKCS7((IPrivateKey)null, chain, hashAlgorithm, false); + PdfPKCS7 sgn = new PdfPKCS7((IPrivateKey)null, chain, hashAlgorithm, externalDigest, false); if (signaturePolicy != null) { sgn.SetSignaturePolicy(signaturePolicy); } Stream data = GetRangeStream(); - byte[] hash = DigestAlgorithms.Digest(data, SignUtils.GetMessageDigest(hashAlgorithm)); + byte[] hash = DigestAlgorithms.Digest(data, hashAlgorithm, externalDigest); IList ocspList = new List(); if (chain.Length > 1 && ocspClient != null) { for (int j = 0; j < chain.Length - 1; ++j) { @@ -768,7 +837,7 @@ public virtual void Timestamp(ITSAClient tsa, String signatureName) { exc.Put(PdfName.Contents, contentEstimated * 2 + 2); PreClose(exc); Stream data = GetRangeStream(); - IDigest messageDigest = tsa.GetMessageDigest(); + IMessageDigest messageDigest = tsa.GetMessageDigest(); byte[] buf = new byte[4096]; int n; while ((n = data.Read(buf)) > 0) { diff --git a/itext/itext.sign/itext/signatures/PdfTwoPhaseSigner.cs b/itext/itext.sign/itext/signatures/PdfTwoPhaseSigner.cs index 0ed0fee311..5861774d90 100644 --- a/itext/itext.sign/itext/signatures/PdfTwoPhaseSigner.cs +++ b/itext/itext.sign/itext/signatures/PdfTwoPhaseSigner.cs @@ -1,30 +1,28 @@ /* - 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; +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.Collections.Generic; using System.IO; -using iText.Commons.Bouncycastle.Cert; -using iText.Commons.Bouncycastle.Crypto; using iText.Kernel.Exceptions; using iText.Kernel.Pdf; using iText.Signatures.Cms; @@ -36,6 +34,8 @@ public class PdfTwoPhaseSigner { private readonly Stream outputStream; + private IExternalDigest externalDigest; + private StampingProperties stampingProperties = new StampingProperties().UseAppendMode(); private bool closed; @@ -62,10 +62,38 @@ public PdfTwoPhaseSigner(PdfReader reader, Stream outputStream) { /// the message digest of the prepared document. public virtual byte[] PrepareDocumentForSignature(SignerProperties signerProperties, String digestAlgorithm , PdfName filter, PdfName subFilter, int estimatedSize, bool includeDate) { - IDigest digest; - digest = SignUtils.GetMessageDigest(digestAlgorithm); - return PrepareDocumentForSignature(signerProperties, digest, filter, subFilter, estimatedSize, includeDate - ); + if (closed) { + throw new PdfException(SignExceptionMessageConstant.THIS_INSTANCE_OF_PDF_SIGNER_ALREADY_CLOSED); + } + PdfSigner pdfSigner = CreatePdfSigner(signerProperties); + PdfDocument document = pdfSigner.GetDocument(); + if (document.GetPdfVersion().CompareTo(PdfVersion.PDF_2_0) < 0) { + document.GetCatalog().AddDeveloperExtension(PdfDeveloperExtension.ESIC_1_7_EXTENSIONLEVEL2); + } + document.GetCatalog().AddDeveloperExtension(PdfDeveloperExtension.ISO_32002); + document.GetCatalog().AddDeveloperExtension(PdfDeveloperExtension.ISO_32001); + PdfSignature cryptoDictionary = pdfSigner.CreateSignatureDictionary(includeDate); + cryptoDictionary.Put(PdfName.Filter, filter); + cryptoDictionary.Put(PdfName.SubFilter, subFilter); + pdfSigner.cryptoDictionary = cryptoDictionary; + IDictionary exc = new Dictionary(); + exc.Put(PdfName.Contents, estimatedSize * 2 + 2); + pdfSigner.PreClose(exc); + Stream data = pdfSigner.GetRangeStream(); + byte[] digest; + if (externalDigest != null) { + digest = DigestAlgorithms.Digest(data, digestAlgorithm, externalDigest); + } + else { + digest = DigestAlgorithms.Digest(data, SignUtils.GetMessageDigest(digestAlgorithm)); + } + byte[] paddedSig = new byte[estimatedSize]; + PdfDictionary dic2 = new PdfDictionary(); + dic2.Put(PdfName.Contents, new PdfString(paddedSig).SetHexWriting(true)); + pdfSigner.Close(dic2); + pdfSigner.closed = true; + closed = true; + return digest; } /// Adds an existing signature to a PDF where space was already reserved. @@ -90,6 +118,17 @@ public static void AddSignatureToPreparedDocument(PdfDocument document, String f applier.Apply((a) => signedContent); } + /// Use the external digest to inject specific digest implementations + /// the IExternalDigest instance to use to generate Digests + /// + /// same instance of + /// + /// + public virtual iText.Signatures.PdfTwoPhaseSigner SetExternalDigest(IExternalDigest externalDigest) { + this.externalDigest = externalDigest; + return this; + } + /// Set stamping properties to be used during main signing operation. /// /// Set stamping properties to be used during main signing operation. @@ -112,53 +151,7 @@ public virtual iText.Signatures.PdfTwoPhaseSigner SetStampingProperties(Stamping } internal virtual PdfSigner CreatePdfSigner(SignerProperties signerProperties) { - PdfSigner signer = new PdfSigner(reader, outputStream, null, stampingProperties); - signer.SetFieldLockDict(signerProperties.GetFieldLockDict()); - signer.SetFieldName(signerProperties.GetFieldName()); - // We need to update field name because signer could change it - signerProperties.SetFieldName(signer.GetFieldName()); - signer.SetCertificationLevel(signerProperties.GetCertificationLevel()); - signer.SetPageRect(signerProperties.GetPageRect()); - signer.SetPageNumber(signerProperties.GetPageNumber()); - signer.SetSignDate(signerProperties.GetSignDate()); - signer.SetSignatureCreator(signerProperties.GetSignatureCreator()); - signer.SetContact(signerProperties.GetContact()); - signer.SetReason(signerProperties.GetReason()); - signer.SetLocation(signerProperties.GetLocation()); - signer.SetSignatureAppearance(signerProperties.GetSignatureAppearance()); - return signer; - } - - private byte[] PrepareDocumentForSignature(SignerProperties signerProperties, IDigest messageDigest, PdfName - filter, PdfName subFilter, int estimatedSize, bool includeDate) { - if (closed) { - throw new PdfException(SignExceptionMessageConstant.THIS_INSTANCE_OF_PDF_SIGNER_ALREADY_CLOSED); - } - PdfSigner pdfSigner = CreatePdfSigner(signerProperties); - - PdfDocument document = pdfSigner.GetDocument(); - if (document.GetPdfVersion().CompareTo(PdfVersion.PDF_2_0) < 0) { - document.GetCatalog().AddDeveloperExtension(PdfDeveloperExtension.ESIC_1_7_EXTENSIONLEVEL2); - } - document.GetCatalog().AddDeveloperExtension(PdfDeveloperExtension.ISO_32002); - document.GetCatalog().AddDeveloperExtension(PdfDeveloperExtension.ISO_32001); - - PdfSignature cryptoDictionary = pdfSigner.CreateSignatureDictionary(includeDate); - cryptoDictionary.Put(PdfName.Filter, filter); - cryptoDictionary.Put(PdfName.SubFilter, subFilter); - pdfSigner.cryptoDictionary = cryptoDictionary; - IDictionary exc = new Dictionary(); - exc.Put(PdfName.Contents, estimatedSize * 2 + 2); - pdfSigner.PreClose(exc); - Stream data = pdfSigner.GetRangeStream(); - byte[] digest = DigestAlgorithms.Digest(data, messageDigest); - byte[] paddedSig = new byte[estimatedSize]; - PdfDictionary dic2 = new PdfDictionary(); - dic2.Put(PdfName.Contents, new PdfString(paddedSig).SetHexWriting(true)); - pdfSigner.Close(dic2); - pdfSigner.closed = true; - closed = true; - return digest; + return new PdfSigner(reader, outputStream, null, stampingProperties, signerProperties); } } -} \ No newline at end of file +} diff --git a/itext/itext.sign/itext/signatures/SignUtils.cs b/itext/itext.sign/itext/signatures/SignUtils.cs index 6ec496806f..90ff2ec818 100644 --- a/itext/itext.sign/itext/signatures/SignUtils.cs +++ b/itext/itext.sign/itext/signatures/SignUtils.cs @@ -37,6 +37,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Bouncycastle.Crypto; using iText.Commons.Bouncycastle.Math; using iText.Commons.Bouncycastle.Tsp; +using iText.Commons.Digest; using iText.Kernel.Exceptions; using iText.Kernel.Pdf; using iText.Signatures.Exceptions; @@ -84,7 +85,11 @@ internal static byte[] GetExtensionValueByOid(IX509Crl crl, String oid) { } internal static IDigest GetMessageDigest(String hashAlgorithm) { - return FACTORY.CreateIDigest(hashAlgorithm); + return (IDigest)new BouncyCastleDigest().GetMessageDigest(hashAlgorithm); + } + + internal static IMessageDigest GetMessageDigest(String hashAlgorithm, IExternalDigest externalDigest) { + return externalDigest.GetMessageDigest(hashAlgorithm); } internal static Stream GetHttpResponse(Uri urlt) { diff --git a/itext/itext.sign/itext/signatures/cms/SignerInfo.cs b/itext/itext.sign/itext/signatures/cms/SignerInfo.cs index 7271bdbb95..898e290cad 100644 --- a/itext/itext.sign/itext/signatures/cms/SignerInfo.cs +++ b/itext/itext.sign/itext/signatures/cms/SignerInfo.cs @@ -29,7 +29,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Bouncycastle.Asn1.Ocsp; using iText.Commons.Bouncycastle.Asn1.X509; using iText.Commons.Bouncycastle.Cert; -using iText.Commons.Bouncycastle.Crypto; +using iText.Commons.Digest; using iText.Commons.Utils; using iText.Kernel.Exceptions; using iText.Signatures; @@ -202,7 +202,7 @@ public virtual void AddSignerCertificateToSignedAttributes(IX509Certificate cert if (signedAttributesReadOnly) { throw new InvalidOperationException(SignExceptionMessageConstant.CMS_SIGNERINFO_READONLY); } - IDigest md = DigestAlgorithms.GetMessageDigestFromOid(digestAlgorithmOid); + IMessageDigest md = DigestAlgorithms.GetMessageDigestFromOid(digestAlgorithmOid); IAsn1EncodableVector certContents = BC_FACTORY.CreateASN1EncodableVector(); // don't add if it is the default value if (!SecurityIDs.ID_SHA256.Equals(digestAlgorithmOid)) { diff --git a/port-hash b/port-hash index 1a36faf6e3..37a74860c4 100644 --- a/port-hash +++ b/port-hash @@ -1 +1 @@ -abe3f098b9d6dedcab048715f32f1de25b60e65c +6c148671399e3139a12b53b220048d1742ee2655