@@ -23,6 +23,9 @@ This file is part of the iText (R) project.
23
23
package com .itextpdf .signatures ;
24
24
25
25
import com .itextpdf .bouncycastleconnector .BouncyCastleFactoryCreator ;
26
+ import com .itextpdf .commons .bouncycastle .IBouncyCastleFactory ;
27
+ import com .itextpdf .commons .bouncycastle .asn1 .IASN1EncodableVector ;
28
+ import com .itextpdf .commons .bouncycastle .asn1 .IASN1Sequence ;
26
29
import com .itextpdf .commons .bouncycastle .asn1 .esf .ISignaturePolicyIdentifier ;
27
30
import com .itextpdf .commons .utils .FileUtil ;
28
31
import com .itextpdf .commons .utils .MessageFormatUtil ;
@@ -46,6 +49,8 @@ This file is part of the iText (R) project.
46
49
import com .itextpdf .kernel .font .PdfFont ;
47
50
import com .itextpdf .kernel .geom .Rectangle ;
48
51
import com .itextpdf .kernel .mac .IMacContainerLocator ;
52
+ import com .itextpdf .signatures .cms .CMSContainer ;
53
+ import com .itextpdf .signatures .cms .CmsAttribute ;
49
54
import com .itextpdf .signatures .mac .SignatureContainerGenerationEvent ;
50
55
import com .itextpdf .kernel .pdf .PdfArray ;
51
56
import com .itextpdf .kernel .pdf .PdfDate ;
@@ -104,7 +109,9 @@ This file is part of the iText (R) project.
104
109
* Takes care of the cryptographic options and appearances that form a signature.
105
110
*/
106
111
public class PdfSigner {
107
- private static final int MAXIMUM_MAC_SIZE = 788 ;
112
+ static final int MAXIMUM_MAC_SIZE = 788 ;
113
+ private static final IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator .getFactory ();
114
+ private static final String ID_ATTR_PDF_MAC_DATA = "1.0.32004.1.2" ;
108
115
109
116
/**
110
117
* Enum containing the Cryptographic Standards. Possible values are "CMS" and "CADES".
@@ -598,8 +605,8 @@ public void signDetached(IExternalDigest externalDigest, IExternalSignature exte
598
605
if (tsaClient != null ) {
599
606
estimatedSize += tsaClient .getTokenSizeEstimate () + 96 ;
600
607
}
601
- if (document .getTrailer ().getAsDictionary ( PdfName . AuthCode ) != null ) {
602
- // if AuthCode is found in trailer , we assume MAC will be embedded and allocate additional space.
608
+ if (document .getDiContainer ().getInstance ( IMacContainerLocator . class ). isMacContainerLocated () ) {
609
+ // If MAC container was located , we presume MAC will be embedded and allocate additional space.
603
610
estimatedSize += MAXIMUM_MAC_SIZE ;
604
611
}
605
612
}
@@ -700,12 +707,18 @@ public void signExternalContainer(IExternalSignatureContainer externalSignatureC
700
707
externalSignatureContainer .modifySigningDictionary (dic .getPdfObject ());
701
708
cryptoDictionary = dic ;
702
709
710
+ if (document .getDiContainer ().getInstance (IMacContainerLocator .class ).isMacContainerLocated ()) {
711
+ // If MAC container was located, we presume MAC will be embedded and allocate additional space.
712
+ estimatedSize += MAXIMUM_MAC_SIZE ;
713
+ }
714
+
703
715
Map <PdfName , Integer > exc = new HashMap <>();
704
716
exc .put (PdfName .Contents , estimatedSize * 2 + 2 );
705
717
preClose (exc );
706
718
707
719
InputStream data = getRangeStream ();
708
720
byte [] encodedSig = externalSignatureContainer .sign (data );
721
+ encodedSig = embedMacTokenIntoSignatureContainer (encodedSig );
709
722
710
723
if (estimatedSize < encodedSig .length ) {
711
724
throw new IOException (SignExceptionMessageConstant .NOT_ENOUGH_SPACE );
@@ -744,6 +757,10 @@ public void timestamp(ITSAClient tsa, String signatureName) throws IOException,
744
757
}
745
758
746
759
int contentEstimated = tsa .getTokenSizeEstimate ();
760
+ if (document .getDiContainer ().getInstance (IMacContainerLocator .class ).isMacContainerLocated ()) {
761
+ // If MAC container was located, we presume MAC will be embedded and allocate additional space.
762
+ contentEstimated += MAXIMUM_MAC_SIZE ;
763
+ }
747
764
if (!isDocumentPdf2 ()) {
748
765
addDeveloperExtension (PdfDeveloperExtension .ESIC_1_7_EXTENSIONLEVEL5 );
749
766
}
@@ -771,6 +788,8 @@ public void timestamp(ITSAClient tsa, String signatureName) throws IOException,
771
788
throw new GeneralSecurityException (e .getMessage (), e );
772
789
}
773
790
791
+ tsToken = embedMacTokenIntoSignatureContainer (tsToken );
792
+
774
793
if (contentEstimated + 2 < tsToken .length ) {
775
794
throw new IOException (MessageFormatUtil .format (
776
795
SignExceptionMessageConstant .TOKEN_ESTIMATION_SIZE_IS_NOT_LARGE_ENOUGH ,
@@ -1308,6 +1327,19 @@ protected int getWidgetPageNumber(PdfWidgetAnnotation widget) {
1308
1327
return pageNumber ;
1309
1328
}
1310
1329
1330
+ PdfSignature createSignatureDictionary (boolean includeDate ) {
1331
+ PdfSignature dic = new PdfSignature ();
1332
+ dic .setReason (this .signerProperties .getReason ());
1333
+ dic .setLocation (this .signerProperties .getLocation ());
1334
+ dic .setSignatureCreator (this .signerProperties .getSignatureCreator ());
1335
+ dic .setContact (this .signerProperties .getContact ());
1336
+ Calendar claimedSignDate = this .signerProperties .getClaimedSignDate ();
1337
+ if (includeDate && claimedSignDate != TimestampConstants .UNDEFINED_TIMESTAMP_DATE ) {
1338
+ dic .setDate (new PdfDate (claimedSignDate )); // time-stamp will over-rule this
1339
+ }
1340
+ return dic ;
1341
+ }
1342
+
1311
1343
private static String getSignerName (X509Certificate certificate ) {
1312
1344
String name = null ;
1313
1345
CertificateInfo .X500Name x500name = CertificateInfo .getSubjectFields (certificate );
@@ -1355,20 +1387,6 @@ private boolean isDocumentPdf2() {
1355
1387
return document .getPdfVersion ().compareTo (PdfVersion .PDF_2_0 ) >= 0 ;
1356
1388
}
1357
1389
1358
- PdfSignature createSignatureDictionary (boolean includeDate ) {
1359
- PdfSignature dic = new PdfSignature ();
1360
- dic .setReason (this .signerProperties .getReason ());
1361
- dic .setLocation (this .signerProperties .getLocation ());
1362
- dic .setSignatureCreator (this .signerProperties .getSignatureCreator ());
1363
- dic .setContact (this .signerProperties .getContact ());
1364
- Calendar claimedSignDate = this .signerProperties .getClaimedSignDate ();
1365
- if (includeDate && claimedSignDate != TimestampConstants .UNDEFINED_TIMESTAMP_DATE ) {
1366
- dic .setDate (new PdfDate (claimedSignDate )); // time-stamp will over-rule this
1367
- }
1368
- return dic ;
1369
- }
1370
-
1371
-
1372
1390
protected void applyAccessibilityProperties (PdfFormField formField , IAccessibleElement modelElement ,
1373
1391
PdfDocument pdfDocument ) {
1374
1392
if (!pdfDocument .isTagged ()) {
@@ -1381,6 +1399,30 @@ protected void applyAccessibilityProperties(PdfFormField formField, IAccessibleE
1381
1399
}
1382
1400
}
1383
1401
1402
+ private byte [] embedMacTokenIntoSignatureContainer (byte [] signatureContainer ) {
1403
+ if (document .getDiContainer ().getInstance (IMacContainerLocator .class ).isMacContainerLocated ()) {
1404
+ try {
1405
+ CMSContainer cmsContainer = new CMSContainer (signatureContainer );
1406
+ // If MAC is in the signature already, we regenerate it anyway.
1407
+ cmsContainer .getSignerInfo ().removeUnSignedAttribute (ID_ATTR_PDF_MAC_DATA );
1408
+ IASN1EncodableVector unsignedVector = FACTORY .createASN1EncodableVector ();
1409
+ document .dispatchEvent (new SignatureContainerGenerationEvent (unsignedVector ,
1410
+ cmsContainer .getSignerInfo ().getSignatureData (), getRangeStream ()));
1411
+ if (FACTORY .createDERSequence (unsignedVector ).size () != 0 ) {
1412
+ IASN1Sequence sequence =
1413
+ FACTORY .createASN1Sequence (FACTORY .createDERSequence (unsignedVector ).getObjectAt (0 ));
1414
+ cmsContainer .getSignerInfo ().addUnSignedAttribute (new CmsAttribute (
1415
+ FACTORY .createASN1ObjectIdentifier (sequence .getObjectAt (0 )).getId (),
1416
+ sequence .getObjectAt (1 ).toASN1Primitive ()));
1417
+ return cmsContainer .serialize ();
1418
+ }
1419
+ } catch (Exception exception ) {
1420
+ throw new PdfException (SignExceptionMessageConstant .NOT_POSSIBLE_TO_EMBED_MAC_TO_SIGNATURE , exception );
1421
+ }
1422
+ }
1423
+ return signatureContainer ;
1424
+ }
1425
+
1384
1426
private void applyDefaultPropertiesForTheNewField (PdfSignatureFormField sigField ) {
1385
1427
SignatureFieldAppearance formFieldElement = getSignatureAppearance ();
1386
1428
PdfFormAnnotation annotation = sigField .getFirstFormAnnotation ();
0 commit comments