1+ /*
2+ This file is part of the iText (R) project.
3+ Copyright (c) 1998-2023 Apryse Group NV
4+ Authors: Apryse Software.
5+
6+ This program is offered under a commercial and under the AGPL license.
7+ For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
8+
9+ AGPL licensing:
10+ This program is free software: you can redistribute it and/or modify
11+ it under the terms of the GNU Affero General Public License as published by
12+ the Free Software Foundation, either version 3 of the License, or
13+ (at your option) any later version.
14+
15+ This program is distributed in the hope that it will be useful,
16+ but WITHOUT ANY WARRANTY; without even the implied warranty of
17+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+ GNU Affero General Public License for more details.
19+
20+ You should have received a copy of the GNU Affero General Public License
21+ along with this program. If not, see <https://www.gnu.org/licenses/>.
22+ */
23+ package com .itextpdf .signatures ;
24+
25+ import com .itextpdf .bouncycastleconnector .BouncyCastleFactoryCreator ;
26+ import com .itextpdf .commons .bouncycastle .IBouncyCastleFactory ;
27+ import com .itextpdf .commons .bouncycastle .operator .AbstractOperatorCreationException ;
28+ import com .itextpdf .commons .bouncycastle .pkcs .AbstractPKCSException ;
29+ import com .itextpdf .commons .utils .Base64 ;
30+ import com .itextpdf .commons .utils .DateTimeUtil ;
31+ import com .itextpdf .io .source .ByteArrayOutputStream ;
32+ import com .itextpdf .kernel .pdf .PdfDocument ;
33+ import com .itextpdf .kernel .pdf .PdfReader ;
34+ import com .itextpdf .kernel .pdf .PdfVersion ;
35+ import com .itextpdf .kernel .pdf .PdfWriter ;
36+ import com .itextpdf .kernel .pdf .StampingProperties ;
37+ import com .itextpdf .kernel .pdf .WriterProperties ;
38+ import com .itextpdf .signatures .testutils .PemFileHelper ;
39+ import com .itextpdf .signatures .testutils .SignaturesCompareTool ;
40+ import com .itextpdf .signatures .testutils .TimeTestUtil ;
41+ import com .itextpdf .signatures .testutils .builder .TestCrlBuilder ;
42+ import com .itextpdf .signatures .testutils .client .TestCrlClient ;
43+ import com .itextpdf .signatures .testutils .client .TestOcspClient ;
44+ import com .itextpdf .signatures .testutils .client .TestTsaClient ;
45+ import com .itextpdf .test .ExtendedITextTest ;
46+ import com .itextpdf .test .annotations .type .BouncyCastleUnitTest ;
47+ import org .junit .Assert ;
48+ import org .junit .Before ;
49+ import org .junit .BeforeClass ;
50+ import org .junit .Test ;
51+ import org .junit .experimental .categories .Category ;
52+
53+ import java .io .ByteArrayInputStream ;
54+ import java .io .FileOutputStream ;
55+ import java .io .IOException ;
56+ import java .security .GeneralSecurityException ;
57+ import java .security .PrivateKey ;
58+ import java .security .Security ;
59+ import java .security .cert .Certificate ;
60+ import java .security .cert .CertificateException ;
61+ import java .security .cert .X509Certificate ;
62+ import java .util .Arrays ;
63+
64+ @ Category (BouncyCastleUnitTest .class )
65+ public class PKCS7ExternalSignatureContainerTest extends ExtendedITextTest {
66+ private static final IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator .getFactory ();
67+ private static final boolean FIPS_MODE = "BCFIPS" .equals (FACTORY .getProviderName ());
68+
69+ private static final String SOURCE_FOLDER = "./src/test/resources/com/itextpdf/signatures/PKCS7ExternalSignatureContainerTest/" ;
70+ private static final String DESTINATION_FOLDER = "./target/test/com/itextpdf/signatures/PKCS7ExternalSignatureContainerTest/" ;
71+ private static final String CERTS_SRC = "./src/test/resources/com/itextpdf/signatures/certs/" ;
72+
73+ private static final char [] PASSWORD = "testpassphrase" .toCharArray ();
74+
75+ private final static String POLICY_IDENTIFIER = "2.16.724.1.3.1.1.2.1.9" ;
76+ private final static String POLICY_HASH_BASE64 = "G7roucf600+f03r/o0bAOQ6WAs0=" ;
77+ private final static byte [] POLICY_HASH = Base64 .decode (POLICY_HASH_BASE64 );
78+ private final static String POLICY_DIGEST_ALGORITHM = "SHA-256" ;
79+ private final static String POLICY_URI = "https://sede.060.gob.es/politica_de_firma_anexo_1.pdf" ;
80+
81+ private Certificate [] chain ;
82+ private PrivateKey pk ;
83+
84+ private X509Certificate caCert ;
85+ private PrivateKey caPrivateKey ;
86+
87+ @ BeforeClass
88+ public static void before () {
89+ Security .addProvider (FACTORY .getProvider ());
90+ createOrClearDestinationFolder (DESTINATION_FOLDER );
91+ }
92+
93+ @ Before
94+ public void init ()
95+ throws IOException , CertificateException , AbstractPKCSException , AbstractOperatorCreationException {
96+ pk = PemFileHelper .readFirstKey (CERTS_SRC + "signCertRsa01.pem" , PASSWORD );
97+ chain = PemFileHelper .readFirstChain (CERTS_SRC + "signCertRsa01.pem" );
98+
99+ String caCertP12FileName = CERTS_SRC + "rootRsa.pem" ;
100+ caCert = (X509Certificate ) PemFileHelper .readFirstChain (caCertP12FileName )[0 ];
101+ caPrivateKey = PemFileHelper .readFirstKey (caCertP12FileName , PASSWORD );
102+ }
103+
104+ @ Test
105+ public void testTroughPdfSigner () throws IOException , GeneralSecurityException {
106+ String outFileName = DESTINATION_FOLDER + "testTroughPdfSigner.pdf" ;
107+ String cmpFileName = SOURCE_FOLDER + "cmp_testTroughPdfSigner.pdf" ;
108+ PdfSigner pdfSigner = new PdfSigner (new PdfReader (createSimpleDocument ()),
109+ new FileOutputStream (outFileName ), new StampingProperties ());
110+ PKCS7ExternalSignatureContainer pkcs7ExternalSignatureContainer = new PKCS7ExternalSignatureContainer (
111+ pk , chain , DigestAlgorithms .SHA256 );
112+ pdfSigner .signExternalContainer (pkcs7ExternalSignatureContainer , 12000 );
113+
114+ Assert .assertNull (SignaturesCompareTool .compareSignatures (outFileName , cmpFileName ));
115+ }
116+
117+ @ Test
118+ public void testTroughPdfSignerWithCrlClient () throws IOException , GeneralSecurityException {
119+ String outFileName = DESTINATION_FOLDER + "testTroughPdfSignerWithCrlClient.pdf" ;
120+ String cmpFileName = SOURCE_FOLDER + "cmp_testTroughPdfSignerWithCrlClient.pdf" ;
121+ PdfSigner pdfSigner = new PdfSigner (new PdfReader (createSimpleDocument ()),
122+ new FileOutputStream (outFileName ), new StampingProperties ());
123+ PKCS7ExternalSignatureContainer pkcs7ExternalSignatureContainer = new PKCS7ExternalSignatureContainer (
124+ pk , chain , DigestAlgorithms .SHA256 );
125+
126+ TestCrlClient crlClient = new TestCrlClient ();
127+
128+ TestCrlBuilder crlBuilder = new TestCrlBuilder (caCert , caPrivateKey , DateTimeUtil .addDaysToDate (TimeTestUtil .TEST_DATE_TIME , -1 ));
129+ crlClient .addBuilderForCertIssuer (crlBuilder );
130+ pkcs7ExternalSignatureContainer .setCrlClient (crlClient );
131+
132+ pdfSigner .signExternalContainer (pkcs7ExternalSignatureContainer , 12000 );
133+
134+ Assert .assertNull (SignaturesCompareTool .compareSignatures (outFileName , cmpFileName ));
135+ }
136+
137+ @ Test
138+ public void testTroughPdfSignerWithOcspClient () throws IOException , GeneralSecurityException {
139+ String outFileName = DESTINATION_FOLDER + "testTroughPdfSignerWithOcspClient.pdf" ;
140+ String cmpFileName = SOURCE_FOLDER + "cmp_testTroughPdfSignerWithOcspClient.pdf" ;
141+ PdfSigner pdfSigner = new PdfSigner (new PdfReader (createSimpleDocument ()),
142+ new FileOutputStream (outFileName ), new StampingProperties ());
143+ PKCS7ExternalSignatureContainer pkcs7ExternalSignatureContainer = new PKCS7ExternalSignatureContainer (
144+ pk , chain , DigestAlgorithms .SHA256 );
145+
146+ TestOcspClient ocspClient = new TestOcspClient ();
147+
148+ ocspClient .addBuilderForCertIssuer (caCert , caPrivateKey );
149+ pkcs7ExternalSignatureContainer .setOcspClient (ocspClient );
150+ pdfSigner .signExternalContainer (pkcs7ExternalSignatureContainer , 12000 );
151+
152+ Assert .assertNull (SignaturesCompareTool .compareSignatures (outFileName , cmpFileName ));
153+ }
154+
155+ @ Test
156+ public void testTroughPdfSignerWithTsaClient () throws IOException , GeneralSecurityException , AbstractOperatorCreationException , AbstractPKCSException {
157+ String outFileName = DESTINATION_FOLDER + "testTroughPdfSignerWithTsaClient.pdf" ;
158+ String cmpFileName = SOURCE_FOLDER + "cmp_testTroughPdfSignerWithTsaClient.pdf" ;
159+ if (FIPS_MODE ) {
160+ cmpFileName = cmpFileName .replace (".pdf" , "_FIPS.pdf" );
161+ }
162+ PdfSigner pdfSigner = new PdfSigner (new PdfReader (createSimpleDocument ()),
163+ new FileOutputStream (outFileName ), new StampingProperties ());
164+ PKCS7ExternalSignatureContainer pkcs7ExternalSignatureContainer = new PKCS7ExternalSignatureContainer (
165+ pk , chain , DigestAlgorithms .SHA256 );
166+ String tsaCertP12FileName = CERTS_SRC + "tsCertRsa.pem" ;
167+
168+ pkcs7ExternalSignatureContainer .setTsaClient (prepareTsaClient (tsaCertP12FileName ));
169+
170+ pdfSigner .signExternalContainer (pkcs7ExternalSignatureContainer , 12000 );
171+
172+ Assert .assertNull (SignaturesCompareTool .compareSignatures (outFileName , cmpFileName ));
173+ }
174+
175+ @ Test
176+ public void testTroughPdfSignerWithCadesType () throws IOException , GeneralSecurityException {
177+ String outFileName = DESTINATION_FOLDER + "testTroughPdfSignerWithCadesType.pdf" ;
178+ String cmpFileName = SOURCE_FOLDER + "cmp_testTroughPdfSignerWithCadesType.pdf" ;
179+ PdfSigner pdfSigner = new PdfSigner (new PdfReader (createSimpleDocument ()),
180+ new FileOutputStream (outFileName ), new StampingProperties ());
181+ PKCS7ExternalSignatureContainer pkcs7ExternalSignatureContainer = new PKCS7ExternalSignatureContainer (
182+ pk , chain , DigestAlgorithms .SHA256 );
183+ pkcs7ExternalSignatureContainer .setSignatureType (PdfSigner .CryptoStandard .CADES );
184+ pdfSigner .signExternalContainer (pkcs7ExternalSignatureContainer , 12000 );
185+
186+ Assert .assertNull (SignaturesCompareTool .compareSignatures (outFileName , cmpFileName ));
187+ }
188+
189+ @ Test
190+ public void testTroughPdfSignerWithSignaturePolicy () throws IOException , GeneralSecurityException {
191+ String outFileName = DESTINATION_FOLDER + "testTroughPdfSignerWithSignaturePolicy.pdf" ;
192+ String cmpFileName = SOURCE_FOLDER + "cmp_testTroughPdfSignerWithSignaturePolicy.pdf" ;
193+ PdfSigner pdfSigner = new PdfSigner (new PdfReader (createSimpleDocument ()),
194+ new FileOutputStream (outFileName ), new StampingProperties ());
195+ PKCS7ExternalSignatureContainer pkcs7ExternalSignatureContainer = new PKCS7ExternalSignatureContainer (
196+ pk , chain , DigestAlgorithms .SHA256 );
197+ SignaturePolicyInfo policy = new SignaturePolicyInfo (POLICY_IDENTIFIER , POLICY_HASH , POLICY_DIGEST_ALGORITHM , POLICY_URI );
198+
199+ pkcs7ExternalSignatureContainer .setSignaturePolicy (policy );
200+ pdfSigner .signExternalContainer (pkcs7ExternalSignatureContainer , 12000 );
201+
202+ Assert .assertNull (SignaturesCompareTool .compareSignatures (outFileName , cmpFileName ));
203+ }
204+
205+ private static ByteArrayInputStream createSimpleDocument () {
206+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream ();
207+ WriterProperties writerProperties = new WriterProperties ().setPdfVersion (PdfVersion .PDF_2_0 );
208+ PdfDocument document = new PdfDocument (new PdfWriter (outputStream , writerProperties ));
209+ document .addNewPage ();
210+ document .close ();
211+ return new ByteArrayInputStream (outputStream .toByteArray ());
212+ }
213+
214+ private static TestTsaClient prepareTsaClient (String tsaCertP12FileName )
215+ throws IOException , CertificateException , AbstractPKCSException , AbstractOperatorCreationException {
216+ Certificate [] tsaChain = PemFileHelper .readFirstChain (tsaCertP12FileName );
217+ PrivateKey tsaPrivateKey = PemFileHelper .readFirstKey (tsaCertP12FileName , PASSWORD );
218+ return new TestTsaClient (Arrays .asList (tsaChain ), tsaPrivateKey );
219+ }
220+ }
0 commit comments