Skip to content

Commit 45f3d61

Browse files
Migrate SigningTest to a separate classes
DEVSIX-5398
1 parent d2cbc0d commit 45f3d61

36 files changed

+883
-441
lines changed
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2021 iText Group NV
4+
Authors: iText 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.sign;
24+
25+
import com.itextpdf.kernel.geom.Rectangle;
26+
import com.itextpdf.kernel.pdf.PdfReader;
27+
import com.itextpdf.kernel.pdf.StampingProperties;
28+
import com.itextpdf.kernel.utils.CompareTool;
29+
import com.itextpdf.signatures.BouncyCastleDigest;
30+
import com.itextpdf.signatures.DigestAlgorithms;
31+
import com.itextpdf.signatures.IExternalSignature;
32+
import com.itextpdf.signatures.PdfSignatureAppearance;
33+
import com.itextpdf.signatures.PdfSigner;
34+
import com.itextpdf.signatures.PrivateKeySignature;
35+
import com.itextpdf.signatures.testutils.SignaturesCompareTool;
36+
import com.itextpdf.test.ExtendedITextTest;
37+
import com.itextpdf.test.annotations.type.IntegrationTest;
38+
import com.itextpdf.test.signutils.Pkcs12FileHelper;
39+
40+
import java.io.FileOutputStream;
41+
import java.io.IOException;
42+
import java.security.GeneralSecurityException;
43+
import java.security.KeyStoreException;
44+
import java.security.NoSuchAlgorithmException;
45+
import java.security.PrivateKey;
46+
import java.security.Security;
47+
import java.security.UnrecoverableKeyException;
48+
import java.security.cert.Certificate;
49+
import java.security.cert.CertificateException;
50+
import java.util.Arrays;
51+
import java.util.HashMap;
52+
import java.util.List;
53+
import java.util.Map;
54+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
55+
import org.junit.Assert;
56+
import org.junit.Before;
57+
import org.junit.BeforeClass;
58+
import org.junit.Test;
59+
import org.junit.experimental.categories.Category;
60+
61+
@Category(IntegrationTest.class)
62+
public class AnnotationsSigningTest extends ExtendedITextTest {
63+
64+
private static final String SOURCE_FOLDER = "./src/test/resources/com/itextpdf/signatures/sign/AnnotationsSigningTest/";
65+
private static final String DESTINATION_FOLDER = "./target/test/com/itextpdf/signatures/sign/AnnotationsSigningTest/";
66+
private static final String CERTS_SRC = "./src/test/resources/com/itextpdf/signatures/certs/";
67+
68+
private static final char[] PASSWORD = "testpass".toCharArray();
69+
70+
private Certificate[] chain;
71+
private PrivateKey pk;
72+
73+
@BeforeClass
74+
public static void before() {
75+
Security.addProvider(new BouncyCastleProvider());
76+
createOrClearDestinationFolder(DESTINATION_FOLDER);
77+
}
78+
79+
@Before
80+
public void init()
81+
throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException {
82+
pk = Pkcs12FileHelper.readFirstKey(CERTS_SRC + "signCertRsa01.p12", PASSWORD, PASSWORD);
83+
chain = Pkcs12FileHelper.readFirstChain(CERTS_SRC + "signCertRsa01.p12", PASSWORD);
84+
}
85+
86+
@Test
87+
public void signingDocumentAppendModeIndirectPageAnnotsTest()
88+
throws GeneralSecurityException, IOException, InterruptedException {
89+
String srcFile = SOURCE_FOLDER + "annotsIndirect.pdf";
90+
String cmpPdf = SOURCE_FOLDER + "cmp_annotsIndirect.pdf";
91+
String outPdf = DESTINATION_FOLDER + "annotsIndirect";
92+
93+
Rectangle rect = new Rectangle(30, 200, 200, 100);
94+
95+
String fieldName = "Signature1";
96+
sign(srcFile, fieldName, outPdf, chain, pk, DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CADES, "Test 1",
97+
"TestCity", rect, false, true, PdfSigner.NOT_CERTIFIED, 12f);
98+
99+
Assert.assertNull(new CompareTool().compareVisually(outPdf, cmpPdf, DESTINATION_FOLDER, "diff_",
100+
getTestMap(rect)));
101+
102+
Assert.assertNull(SignaturesCompareTool.compareSignatures(outPdf, cmpPdf));
103+
}
104+
105+
@Test
106+
public void signingIntoExistingFieldWithPKeyTest()
107+
throws GeneralSecurityException, IOException, InterruptedException {
108+
//field is merged with widget and has /P key
109+
String srcFile = SOURCE_FOLDER + "emptySignature01.pdf";
110+
String cmpPdf = SOURCE_FOLDER + "cmp_emptySignature01.pdf";
111+
String outPdf = DESTINATION_FOLDER + "emptySignature01.pdf";
112+
113+
String fieldName = "Signature1";
114+
sign(srcFile, fieldName, outPdf, chain, pk, DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CADES, "Test 1",
115+
"TestCity", null, false, false, PdfSigner.NOT_CERTIFIED, 12f);
116+
117+
Assert.assertNull(new CompareTool().compareVisually(outPdf, cmpPdf, DESTINATION_FOLDER, "diff_",
118+
getTestMap(new Rectangle(41, 693, 237, 781))));
119+
120+
Assert.assertNull(SignaturesCompareTool.compareSignatures(outPdf, cmpPdf));
121+
}
122+
123+
@Test
124+
public void signingIntoExistingFieldWithoutPKeyTest()
125+
throws GeneralSecurityException, IOException, InterruptedException {
126+
//field is merged with widget and widget doesn't have /P key
127+
String srcFile = SOURCE_FOLDER + "emptySignature02.pdf";
128+
String cmpPdf = SOURCE_FOLDER + "cmp_emptySignature02.pdf";
129+
String outPdf = DESTINATION_FOLDER + "emptySignature02.pdf";
130+
131+
String fieldName = "Signature1";
132+
sign(srcFile, fieldName, outPdf, chain, pk, DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CADES, "Test 1",
133+
"TestCity", null, false, false, PdfSigner.NOT_CERTIFIED, 12f);
134+
135+
Assert.assertNull(new CompareTool().compareVisually(outPdf, cmpPdf, DESTINATION_FOLDER, "diff_",
136+
getTestMap(new Rectangle(41, 693, 237, 781))));
137+
138+
Assert.assertNull(SignaturesCompareTool.compareSignatures(outPdf, cmpPdf));
139+
}
140+
141+
@Test
142+
public void signingIntoExistingReuseAppearanceTest()
143+
throws GeneralSecurityException, IOException {
144+
String srcFile = SOURCE_FOLDER + "emptySigWithAppearance.pdf";
145+
String cmpPdf = SOURCE_FOLDER + "cmp_emptySigWithAppearance.pdf";
146+
String outPdf = DESTINATION_FOLDER + "emptySigWithAppearance.pdf";
147+
148+
String fieldName = "Signature1";
149+
sign(srcFile, fieldName, outPdf, chain, pk, DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CADES, "Test 1",
150+
"TestCity", null, true, false);
151+
152+
Assert.assertNull(SignaturesCompareTool.compareSignatures(outPdf, cmpPdf));
153+
}
154+
155+
protected void sign(String src, String name, String dest,
156+
Certificate[] chain, PrivateKey pk,
157+
String digestAlgorithm, PdfSigner.CryptoStandard subfilter,
158+
String reason, String location, Rectangle rectangleForNewField, boolean setReuseAppearance,
159+
boolean isAppendMode) throws GeneralSecurityException, IOException {
160+
sign(src, name, dest, chain, pk, digestAlgorithm, subfilter, reason, location, rectangleForNewField,
161+
setReuseAppearance, isAppendMode, PdfSigner.NOT_CERTIFIED, null);
162+
}
163+
164+
protected void sign(String src, String name, String dest,
165+
Certificate[] chain, PrivateKey pk,
166+
String digestAlgorithm, PdfSigner.CryptoStandard subfilter,
167+
String reason, String location, Rectangle rectangleForNewField, boolean setReuseAppearance,
168+
boolean isAppendMode, int certificationLevel, Float fontSize)
169+
throws GeneralSecurityException, IOException {
170+
171+
PdfReader reader = new PdfReader(src);
172+
StampingProperties properties = new StampingProperties();
173+
if (isAppendMode) {
174+
properties.useAppendMode();
175+
}
176+
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), properties);
177+
178+
signer.setCertificationLevel(certificationLevel);
179+
180+
// Creating the appearance
181+
PdfSignatureAppearance appearance = signer.getSignatureAppearance()
182+
.setReason(reason)
183+
.setLocation(location)
184+
.setReuseAppearance(setReuseAppearance);
185+
186+
if (rectangleForNewField != null) {
187+
appearance.setPageRect(rectangleForNewField);
188+
}
189+
if (fontSize != null) {
190+
appearance.setLayer2FontSize((float) fontSize);
191+
}
192+
193+
signer.setFieldName(name);
194+
// Creating the signature
195+
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
196+
signer.signDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, subfilter);
197+
}
198+
199+
private static Map<Integer, List<Rectangle>> getTestMap(Rectangle ignoredArea) {
200+
Map<Integer, List<Rectangle>> result = new HashMap<Integer, List<Rectangle>>();
201+
result.put(1, Arrays.asList(ignoredArea));
202+
return result;
203+
}
204+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2021 iText Group NV
4+
Authors: iText 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.sign;
24+
25+
import com.itextpdf.kernel.PdfException;
26+
import com.itextpdf.kernel.pdf.PdfReader;
27+
import com.itextpdf.kernel.pdf.ReaderProperties;
28+
import com.itextpdf.kernel.pdf.StampingProperties;
29+
import com.itextpdf.signatures.BouncyCastleDigest;
30+
import com.itextpdf.signatures.DigestAlgorithms;
31+
import com.itextpdf.signatures.IExternalSignature;
32+
import com.itextpdf.signatures.PdfSignatureAppearance;
33+
import com.itextpdf.signatures.PdfSigner;
34+
import com.itextpdf.signatures.PrivateKeySignature;
35+
import com.itextpdf.signatures.testutils.SignaturesCompareTool;
36+
import com.itextpdf.test.ExtendedITextTest;
37+
import com.itextpdf.test.annotations.type.IntegrationTest;
38+
import com.itextpdf.test.signutils.Pkcs12FileHelper;
39+
40+
import java.io.FileOutputStream;
41+
import java.io.IOException;
42+
import java.security.GeneralSecurityException;
43+
import java.security.KeyStoreException;
44+
import java.security.NoSuchAlgorithmException;
45+
import java.security.PrivateKey;
46+
import java.security.Security;
47+
import java.security.UnrecoverableKeyException;
48+
import java.security.cert.Certificate;
49+
import java.security.cert.CertificateException;
50+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
51+
import org.junit.Assert;
52+
import org.junit.Before;
53+
import org.junit.BeforeClass;
54+
import org.junit.Test;
55+
import org.junit.experimental.categories.Category;
56+
57+
@Category(IntegrationTest.class)
58+
public class EncryptedSigningTest extends ExtendedITextTest {
59+
60+
private static final String SOURCE_FOLDER = "./src/test/resources/com/itextpdf/signatures/sign"
61+
+ "/EncryptedSigningTest/";
62+
private static final String DESTINATION_FOLDER = "./target/test/com/itextpdf/signatures/sign/EncryptedSigningTest/";
63+
private static final String CERTS_SRC = "./src/test/resources/com/itextpdf/signatures/certs/";
64+
65+
private static final char[] PASSWORD = "testpass".toCharArray();
66+
67+
private Certificate[] chain;
68+
private PrivateKey pk;
69+
70+
@BeforeClass
71+
public static void before() {
72+
Security.addProvider(new BouncyCastleProvider());
73+
createOrClearDestinationFolder(DESTINATION_FOLDER);
74+
}
75+
76+
@Before
77+
public void init()
78+
throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException,
79+
UnrecoverableKeyException {
80+
pk = Pkcs12FileHelper.readFirstKey(CERTS_SRC + "signCertRsa01.p12", PASSWORD, PASSWORD);
81+
chain = Pkcs12FileHelper.readFirstChain(CERTS_SRC + "signCertRsa01.p12", PASSWORD);
82+
}
83+
84+
@Test
85+
public void signEncryptedPdfTest() throws GeneralSecurityException, IOException {
86+
String srcFile = SOURCE_FOLDER + "encrypted.pdf";
87+
String cmpPdf = SOURCE_FOLDER + "cmp_signedEncrypted.pdf";
88+
String outPdf = DESTINATION_FOLDER + "signedEncrypted.pdf";
89+
90+
String fieldName = "Signature1";
91+
92+
byte[] ownerPass = "World".getBytes();
93+
PdfReader reader = new PdfReader(srcFile, new ReaderProperties().setPassword(ownerPass));
94+
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(outPdf),
95+
new StampingProperties().useAppendMode());
96+
97+
// Creating the appearance
98+
PdfSignatureAppearance appearance = signer.getSignatureAppearance()
99+
.setReason("Test1")
100+
.setLocation("TestCity");
101+
102+
signer.setFieldName(fieldName);
103+
// Creating the signature
104+
IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256,
105+
BouncyCastleProvider.PROVIDER_NAME);
106+
signer.signDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES);
107+
108+
//TODO DEVSIX-5637 Improve SignaturesCompareTool#compareSignatures to check encrypted pdf
109+
Assert.assertEquals(PdfException.BadUserPassword, SignaturesCompareTool.compareSignatures(outPdf, cmpPdf));
110+
}
111+
112+
@Test
113+
public void signCertificateSecurityPdfTest() throws IOException, GeneralSecurityException {
114+
String srcFile = SOURCE_FOLDER + "signCertificateSecurityPdf.pdf";
115+
String cmpPdf = SOURCE_FOLDER + "cmp_signCertificateSecurityPdf.pdf";
116+
String outPdf = DESTINATION_FOLDER + "signCertificateSecurityPdf.pdf";
117+
118+
PdfReader reader = new PdfReader(srcFile, new ReaderProperties()
119+
.setPublicKeySecurityParams(chain[0], pk, new BouncyCastleProvider().getName(), null));
120+
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(outPdf),
121+
new StampingProperties().useAppendMode());
122+
123+
// Creating the signature
124+
IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256,
125+
BouncyCastleProvider.PROVIDER_NAME);
126+
signer.signDetached(new BouncyCastleDigest(), pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES);
127+
128+
//TODO DEVSIX-5637 Improve SignaturesCompareTool#compareSignatures to check encrypted pdf
129+
Assert.assertEquals(PdfException.CertificateIsNotProvidedDocumentIsEncryptedWithPublicKeyCertificate,
130+
SignaturesCompareTool.compareSignatures(outPdf, cmpPdf));
131+
}
132+
}

0 commit comments

Comments
 (0)