@@ -43,23 +43,30 @@ This file is part of the iText (R) project.
43
43
package com .itextpdf .signatures .sign ;
44
44
45
45
import com .itextpdf .kernel .geom .Rectangle ;
46
+ import com .itextpdf .kernel .pdf .CompressionConstants ;
47
+ import com .itextpdf .kernel .pdf .PdfDocument ;
48
+ import com .itextpdf .kernel .pdf .PdfName ;
46
49
import com .itextpdf .kernel .pdf .PdfReader ;
47
50
import com .itextpdf .kernel .pdf .StampingProperties ;
48
51
import com .itextpdf .signatures .BouncyCastleDigest ;
49
52
import com .itextpdf .signatures .DigestAlgorithms ;
50
53
import com .itextpdf .signatures .IExternalSignature ;
54
+ import com .itextpdf .signatures .PdfSignatureAppearance ;
51
55
import com .itextpdf .signatures .PdfSigner ;
56
+ import com .itextpdf .signatures .PdfSigner .CryptoStandard ;
52
57
import com .itextpdf .signatures .PrivateKeySignature ;
53
58
import com .itextpdf .test .signutils .Pkcs12FileHelper ;
54
59
import com .itextpdf .test .ExtendedITextTest ;
55
60
import com .itextpdf .test .annotations .type .IntegrationTest ;
61
+
56
62
import java .io .FileOutputStream ;
57
63
import java .io .IOException ;
58
64
import java .security .GeneralSecurityException ;
59
65
import java .security .PrivateKey ;
60
66
import java .security .Security ;
61
67
import java .security .cert .Certificate ;
62
68
import org .bouncycastle .jce .provider .BouncyCastleProvider ;
69
+ import org .junit .Assert ;
63
70
import org .junit .BeforeClass ;
64
71
import org .junit .Test ;
65
72
import org .junit .experimental .categories .Category ;
@@ -101,4 +108,56 @@ public void sequentialSignOfFileWithAnnots() throws IOException, GeneralSecurity
101
108
102
109
PadesSigTest .basicCheckSignedDoc (outFileName , signatureName );
103
110
}
111
+
112
+ @ Test
113
+ public void secondSignOfTaggedDocTest () throws IOException , GeneralSecurityException {
114
+ String signCertFileName = certsSrc + "signCertRsa01.p12" ;
115
+ String outFileName = destinationFolder + "secondSignOfTagged.pdf" ;
116
+ String srcFileName = sourceFolder + "taggedAndSignedDoc.pdf" ;
117
+
118
+ Certificate [] signChain = Pkcs12FileHelper .readFirstChain (signCertFileName , password );
119
+
120
+ PrivateKey signPrivateKey = Pkcs12FileHelper .readFirstKey (signCertFileName , password , password );
121
+
122
+ IExternalSignature pks = new PrivateKeySignature (signPrivateKey , DigestAlgorithms .SHA256 ,
123
+ BouncyCastleProvider .PROVIDER_NAME );
124
+
125
+ String signatureName = "Signature2" ;
126
+ PdfSigner signer = new PdfSigner (new PdfReader (srcFileName ), new FileOutputStream (outFileName ),
127
+ new StampingProperties ().useAppendMode ());
128
+
129
+ PdfDocument document = signer .getDocument ();
130
+ document .getWriter ().setCompressionLevel (CompressionConstants .NO_COMPRESSION );
131
+
132
+ signer .setFieldName (signatureName );
133
+ PdfSignatureAppearance appearance = signer .getSignatureAppearance ();
134
+ appearance .setPageNumber (1 );
135
+ signer .getSignatureAppearance ()
136
+ .setPageRect (new Rectangle (50 , 550 , 200 , 100 ))
137
+ .setReason ("Test2" )
138
+ .setLocation ("TestCity2" )
139
+ .setLayer2Text ("Approval test signature #2.\n Created by iText7." );
140
+
141
+ signer .signDetached (new BouncyCastleDigest (), pks , signChain , null , null ,
142
+ null , 0 , CryptoStandard .CADES );
143
+
144
+ PadesSigTest .basicCheckSignedDoc (outFileName , "Signature1" );
145
+ PadesSigTest .basicCheckSignedDoc (outFileName , "Signature2" );
146
+
147
+ try (PdfDocument twiceSigned = new PdfDocument (new PdfReader (outFileName ));
148
+ PdfDocument resource = new PdfDocument (new PdfReader (srcFileName ))) {
149
+
150
+ float resourceStrElemNumber = resource .getStructTreeRoot ().getPdfObject ().getAsArray (PdfName .K )
151
+ .getAsDictionary (0 ).getAsArray (PdfName .K ).size ();
152
+
153
+ float outStrElemNumber = twiceSigned .getStructTreeRoot ().getPdfObject ().getAsArray (PdfName .K )
154
+ .getAsDictionary (0 ).getAsArray (PdfName .K ).size ();
155
+
156
+ // Here we assert the amount of objects in StructTreeRoot in resource file and twice signed file
157
+ // as the original signature validation failed by Adobe because of struct tree change. If the fix
158
+ // would make this tree unchanged, then the assertion should be adjusted with comparing the tree of
159
+ // objects in StructTreeRoot to ensure that it won't be changed.
160
+ Assert .assertNotEquals (resourceStrElemNumber , outStrElemNumber );
161
+ }
162
+ }
104
163
}
0 commit comments