From 66889350ffa346bd6d913ef16e37c092a401296f Mon Sep 17 00:00:00 2001 From: Angelina Pavlovets Date: Wed, 6 Dec 2023 21:57:57 +0000 Subject: [PATCH] Determine the default digest algorithm based on the signature algorithm in PdfPadesSigner DEVSIX-7961 Autoported commit. Original commit hash: [19ee24c01] Manual files: bouncy-castle-adapter/src/main/java/com/itextpdf/bouncycastle/openssl/PEMParserBC.java bouncy-castle-fips-adapter/src/main/java/com/itextpdf/bouncycastlefips/openssl/PEMParserBCFips.java sign/src/test/java/com/itextpdf/signatures/testutils/PemFileHelper.java --- .../signatures/sign/PdfPadesSignerTest.cs | 52 +++++++++++++++++- .../signatures/certs/signCertEd25519.pem | 11 ++++ .../itext/signatures/certs/signCertEd448.pem | 14 +++++ .../cmp_padesSignatureEd25519Test.pdf | Bin 0 -> 19853 bytes .../cmp_padesSignatureEd448Test.pdf | Bin 0 -> 19965 bytes .../itext/signatures/PdfPadesSigner.cs | 25 +++++++-- port-hash | 2 +- 7 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 itext.tests/itext.sign.tests/resources/itext/signatures/certs/signCertEd25519.pem create mode 100644 itext.tests/itext.sign.tests/resources/itext/signatures/certs/signCertEd448.pem create mode 100644 itext.tests/itext.sign.tests/resources/itext/signatures/sign/PdfPadesSignerTest/cmp_padesSignatureEd25519Test.pdf create mode 100644 itext.tests/itext.sign.tests/resources/itext/signatures/sign/PdfPadesSignerTest/cmp_padesSignatureEd448Test.pdf diff --git a/itext.tests/itext.sign.tests/itext/signatures/sign/PdfPadesSignerTest.cs b/itext.tests/itext.sign.tests/itext/signatures/sign/PdfPadesSignerTest.cs index a1ed4de0ff..531ad3d73a 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/sign/PdfPadesSignerTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/sign/PdfPadesSignerTest.cs @@ -27,6 +27,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Bouncycastle; using iText.Commons.Bouncycastle.Cert; using iText.Commons.Bouncycastle.Crypto; +using iText.Commons.Bouncycastle.Security; using iText.Commons.Utils; using iText.Forms.Form.Element; using iText.Kernel.Exceptions; @@ -39,7 +40,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Test; namespace iText.Signatures.Sign { - [NUnit.Framework.Category("IntegrationTest")] + [NUnit.Framework.Category("BouncyCastleIntegrationTest")] public class PdfPadesSignerTest : ExtendedITextTest { private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory(); @@ -183,6 +184,55 @@ public virtual void SmallTokenSizeEstimationTest() { Exception exception = NUnit.Framework.Assert.Catch(typeof(IOException), () => padesSigner.SignWithBaselineLTAProfile (signerProperties, signRsaChain, pks, testTsa)); } + + [NUnit.Framework.Test] + public virtual void PadesSignatureEd25519Test() { + NUnit.Framework.Assume.That(!FACTORY.IsInApprovedOnlyMode()); + String fileName = "padesSignatureEd25519Test.pdf"; + String outFileName = destinationFolder + fileName; + String cmpFileName = sourceFolder + "cmp_" + fileName; + String srcFileName = sourceFolder + "helloWorldDoc.pdf"; + String signCertFileName = certsSrc + "signCertEd25519.pem"; + IX509Certificate[] signEdDSAChain = PemFileHelper.ReadFirstChain(signCertFileName); + IPrivateKey signEdDSAPrivateKey = PemFileHelper.ReadFirstKey(signCertFileName, password); + SignerProperties signerProperties = CreateSignerProperties(); + PdfPadesSigner padesSigner = CreatePdfPadesSigner(srcFileName, outFileName); + if (FIPS_MODE) { + // algorithm identifier in key not recognised + Exception exception = NUnit.Framework.Assert.Catch(typeof(PdfException), () => padesSigner.SignWithBaselineBProfile + (signerProperties, signEdDSAChain, signEdDSAPrivateKey)); + NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(SignExceptionMessageConstant.ALGORITHMS_NOT_SUPPORTED, + "SHA512withEd25519", "Ed25519"), exception.Message); + } else { + padesSigner.SignWithBaselineBProfile(signerProperties, signEdDSAChain, signEdDSAPrivateKey); + TestSignUtils.BasicCheckSignedDoc(outFileName, "Signature1"); + NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outFileName, cmpFileName)); + } + } + + [NUnit.Framework.Test] + public virtual void PadesSignatureEd448Test() { + NUnit.Framework.Assume.That(!FACTORY.IsInApprovedOnlyMode()); + String fileName = "padesSignatureEd448Test.pdf"; + String outFileName = destinationFolder + fileName; + String cmpFileName = sourceFolder + "cmp_" + fileName; + String srcFileName = sourceFolder + "helloWorldDoc.pdf"; + String signCertFileName = certsSrc + "signCertEd448.pem"; + IX509Certificate[] signEdDSAChain = PemFileHelper.ReadFirstChain(signCertFileName); + IPrivateKey signEdDSAPrivateKey = PemFileHelper.ReadFirstKey(signCertFileName, password); + SignerProperties signerProperties = CreateSignerProperties(); + PdfPadesSigner padesSigner = CreatePdfPadesSigner(srcFileName, outFileName); + if (FIPS_MODE) { + // SHAKE256 is currently not supported in BCFIPS + Exception exception = NUnit.Framework.Assert.Catch(typeof(AbstractGeneralSecurityException), () => padesSigner.SignWithBaselineBProfile + (signerProperties, signEdDSAChain, signEdDSAPrivateKey)); + } + else { + padesSigner.SignWithBaselineBProfile(signerProperties, signEdDSAChain, signEdDSAPrivateKey); + TestSignUtils.BasicCheckSignedDoc(outFileName, "Signature1"); + NUnit.Framework.Assert.IsNull(SignaturesCompareTool.CompareSignatures(outFileName, cmpFileName)); + } + } private SignerProperties CreateSignerProperties() { SignerProperties signerProperties = new SignerProperties(); diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/certs/signCertEd25519.pem b/itext.tests/itext.sign.tests/resources/itext/signatures/certs/signCertEd25519.pem new file mode 100644 index 0000000000..2126cc0d15 --- /dev/null +++ b/itext.tests/itext.sign.tests/resources/itext/signatures/certs/signCertEd25519.pem @@ -0,0 +1,11 @@ +-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VwBCIEIPIdKJtjErGrsgpBaM04RZa49tMWLFrKDt6fVoGDxdtZ +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIBCDCBuwIUGX/b5h/jmeMPJ11mVZgEfizZc1wwBQYDK2VwMCcxCzAJBgNVBAYT +AkJFMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5jb20wHhcNMjMxMjA2MTQyNzQwWhcN +NDMwMjA0MTQyNzQwWjAnMQswCQYDVQQGEwJCRTEYMBYGA1UEAwwPd3d3LmV4YW1w +bGUuY29tMCowBQYDK2VwAyEAZUXx5GDu4xyo6UKEOqPaxTyna6LGoUswH2ShmyO/ +uJswBQYDK2VwA0EAV1xEcFJunwRzH9ufTGAJ362AbadF5N+hIYd5wxKES8EOkY/2 +TsMbipY6uQLQJP2alusxc5+2varXxskpNGAuDQ== +-----END CERTIFICATE----- diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/certs/signCertEd448.pem b/itext.tests/itext.sign.tests/resources/itext/signatures/certs/signCertEd448.pem new file mode 100644 index 0000000000..304c08469f --- /dev/null +++ b/itext.tests/itext.sign.tests/resources/itext/signatures/certs/signCertEd448.pem @@ -0,0 +1,14 @@ +-----BEGIN PRIVATE KEY----- +MEcCAQAwBQYDK2VxBDsEOfrKlMzLC2KFud/xAxCCT9N8y2mPl8pKyUM3nT3uWYBK +MwG7PWEKk2jVgxLBIjdRATaMFG7SrZJHQQ== +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIBUzCB1AIUZ3HGGxCugYIeKkQjLrCVG90vhqkwBQYDK2VxMCcxCzAJBgNVBAYT +AkJFMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5jb20wHhcNMjMxMjA2MTQ0NzE4WhcN +NDMwMjA0MTQ0NzE4WjAnMQswCQYDVQQGEwJCRTEYMBYGA1UEAwwPd3d3LmV4YW1w +bGUuY29tMEMwBQYDK2VxAzoAO12xP2xDv+3i6DrOUiLkKk4AYf4limP3IstJejo/ +IcL31H7oRZvtNrDlkpdjTmfgmX06KicNVBcAMAUGAytlcQNzALdSj5VltGHj/2OY +lXLeHnwe//gUpEQQBMX+u5MHxBWApGvz1R2yrJ/NASvcQW0703M9KDGD7VY+gAYn +mnPXaXL1RO8mcVpz29/hak6sFEVTFHvoo6NjlAXEjYtkbraf3jCIk77t9KD5oRi1 +T25XxGUUAA== +-----END CERTIFICATE----- diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/sign/PdfPadesSignerTest/cmp_padesSignatureEd25519Test.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/sign/PdfPadesSignerTest/cmp_padesSignatureEd25519Test.pdf new file mode 100644 index 0000000000000000000000000000000000000000..24cb66355bb9f29d3fb566d4516beaf1158febbc GIT binary patch literal 19853 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 H*VBIhrb0+f literal 0 HcmV?d00001 diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/sign/PdfPadesSignerTest/cmp_padesSignatureEd448Test.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/sign/PdfPadesSignerTest/cmp_padesSignatureEd448Test.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5ea04da5508250914f7d48681907e4ee62a8f49f GIT binary patch literal 19965 zcmeI4TWnlM8OKA^hp-e>36%$)4iZ*vRrZmF+zK3vYX*9W0j&ac}+I1=iv59RUD zSsR=$q?w-X4|>5~XkC8c{`Y&Wciy<6p=Aa_!pL zL)XjK79M`~>`rgAP-$)&uX3f=zHq|{E01pk9J3at zr;|C!2#Os;0n$W&czm;R&JOH)cWrku-(5ThIR@=+=LpmqKk@)0R1-lorHn{AN%(z) z+&594==u*|u-NPR%{uhP+biMn;A)|#$P}MkJ~^|veC*UpafJ~=Cez_Xv!Hme*WKJG zPM#?q8J~G@@%ZG$(CfpBMzi^~D zci594g(Hz`6*={ux;h$ZjhB(vzBbbzy<)Xo=)`W3@?)u7>UN<`^KrTTL?|@$7;C~e zxi`G6{=oJIjYf*G*4Wt5Q}eBs*_CTR4A=!t*E2K215;_fmtCKXTgz5Qs+I3M%fBy zOWe$vQ%D<5n1($Lqg5J}5>}`*ESQj-Qo~`~&J2frQ8zCZu-_=Eye6tv65qLs%42;% zaeK}<=M+!E72XB@;UTy8k&lF0 za=975gPWJV{?M7+sNMUd-)5g|w| zc@4EuA4X+!hh!l#D>DnMzwl-8bRA;DEI>uPa&__ZfmC)8# z%GZu*8xVI(oN(H4R3tG$)+jJ7wKugDv5qV@zoGLZE07h)3ScyvI1FwtUy*EE07h)3SP?;4#9~;^ITc+XIk5 zx^;uQ04v}`gS%iHqzeTc0sag1{oA+;&@46{o!xA&d$1K|Ha74)X)lDbA#yAQ+wXR8 z06-H%*2vM7<%Oxa8Gm$n$_L;G&IiARkyviuDeA_qozjfjd1t5_Un(vDrV-o07n^-R zHMS@nSBtrBFBE1k%VUe!QS1;qcHkb27c(2Z$NOQ2?lA)M7~zx5)V=O}w|Aic2LqUi zqnCk9N$`(^Ksma+Fo(Cq`#7_O1StV|*8^2*P8gdgPcI!GKR+03^dBh8OP4N9wfo(vZf~sw(W2vR&zC|PEvL>8F08|u z;@0k?AM-x3ecvkl{AijB9ntoVf>K7nHZz@0chElvN=ZVb{QodFDP@N2micyA2eoBr z5-JVEpS6C$cd0FDYPfi25urO-(1vURRp;@MmGdhl_LYl8gMKNOLOnPq3CJ!4XcFLF zBw0;W-r!`;w*6Wdlq=)d(XoTgUZ4}@nIch6KF+R6kgl2U+=2NyO><#uPiA;;8MQj13ZqejLvIrQ+BDw3`pRQcpxO({N?9?ys znfjKVd+84^KKcCYvClvE?02uc{Nl?`&K_$$_f$PI^YFL7=Ds((@Ypw=iN`+o+*1di z9)Owkr(eDK_E)aIeb+0$HT=uvZ+`Z>@zdWwbm2!&{Nn2;{(AJvGhz7^dMEy~*85?MFgUW5|B26E&6IZwsxcLK1J^ zd;6#-?TL}1W-y<-3J4h{El2Abns2+GY1w;sQ zprUZlGPrimS{wtKP{obVpl)Ef1u7)~loKid!=g1V080YQ5{-U(4@zpW7cLfHqTIlg aqG}f^mHyb6-22DI2w93&;1mtnQvU^*T!rHR literal 0 HcmV?d00001 diff --git a/itext/itext.sign/itext/signatures/PdfPadesSigner.cs b/itext/itext.sign/itext/signatures/PdfPadesSigner.cs index 300bda6229..206bf2e17f 100644 --- a/itext/itext.sign/itext/signatures/PdfPadesSigner.cs +++ b/itext/itext.sign/itext/signatures/PdfPadesSigner.cs @@ -126,7 +126,7 @@ public virtual void SignWithBaselineBProfile(SignerProperties signerProperties, /// public virtual void SignWithBaselineBProfile(SignerProperties signerProperties, IX509Certificate[] chain, IPrivateKey privateKey) { - IExternalSignature externalSignature = new PrivateKeySignature(privateKey, DEFAULT_DIGEST_ALGORITHM); + IExternalSignature externalSignature = new PrivateKeySignature(privateKey, GetDigestAlgorithm(privateKey)); SignWithBaselineBProfile(signerProperties, chain, externalSignature); } @@ -179,7 +179,7 @@ public virtual void SignWithBaselineTProfile(SignerProperties signerProperties, /// public virtual void SignWithBaselineTProfile(SignerProperties signerProperties, IX509Certificate[] chain, IPrivateKey privateKey, ITSAClient tsaClient) { - IExternalSignature externalSignature = new PrivateKeySignature(privateKey, DEFAULT_DIGEST_ALGORITHM); + IExternalSignature externalSignature = new PrivateKeySignature(privateKey, GetDigestAlgorithm(privateKey)); SignWithBaselineTProfile(signerProperties, chain, externalSignature, tsaClient); } @@ -245,7 +245,7 @@ public virtual void SignWithBaselineLTProfile(SignerProperties signerProperties, /// public virtual void SignWithBaselineLTProfile(SignerProperties signerProperties, IX509Certificate[] chain, IPrivateKey privateKey, ITSAClient tsaClient) { - IExternalSignature externalSignature = new PrivateKeySignature(privateKey, DEFAULT_DIGEST_ALGORITHM); + IExternalSignature externalSignature = new PrivateKeySignature(privateKey, GetDigestAlgorithm(privateKey)); SignWithBaselineLTProfile(signerProperties, chain, externalSignature, tsaClient); } @@ -312,7 +312,7 @@ public virtual void SignWithBaselineLTAProfile(SignerProperties signerProperties /// public virtual void SignWithBaselineLTAProfile(SignerProperties signerProperties, IX509Certificate[] chain , IPrivateKey privateKey, ITSAClient tsaClient) { - IExternalSignature externalSignature = new PrivateKeySignature(privateKey, DEFAULT_DIGEST_ALGORITHM); + IExternalSignature externalSignature = new PrivateKeySignature(privateKey, GetDigestAlgorithm(privateKey)); SignWithBaselineLTAProfile(signerProperties, chain, externalSignature, tsaClient); } @@ -624,5 +624,22 @@ private void CreateRevocationClients(IX509Certificate signingCert, bool clientsR ocspClient = new OcspClientBouncyCastle(null); } } + + private String GetDigestAlgorithm(IPrivateKey privateKey) { + String signatureAlgorithm = SignUtils.GetPrivateKeyAlgorithm(privateKey); + switch (signatureAlgorithm) { + case "Ed25519": { + return DigestAlgorithms.SHA512; + } + + case "Ed448": { + return DigestAlgorithms.SHAKE256; + } + + default: { + return DEFAULT_DIGEST_ALGORITHM; + } + } + } } } diff --git a/port-hash b/port-hash index 1e4f940dc7..5930ba657e 100644 --- a/port-hash +++ b/port-hash @@ -1 +1 @@ -15993f567b79c85d1bcaef6d9e680ebe13b492cc +19ee24c01d3a0cbe1e0e64bf2b9383b7fb1dc7da