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