1

I'm new to IText7, and It took me two days to do that.

When generated a pdf have 3 pages, like ...

4 0 obj
<</Contents 5 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj
7 0 obj
<</Contents 8 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj
9 0 obj
<</Contents 10 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj

...

then i signed it, the pdf added some object like this ...

1 0 obj
<</AcroForm 11 0 R/Pages 2 0 R/Type/Catalog>>
endobj
9 0 obj
<</Annots[13 0 R]/Contents 10 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj
11 0 obj
<</Fields[13 0 R]/SigFlags 3>>
endobj
13 0 obj
<</AP<</N 18 0 R>>/F 132/FT/Sig/P 9 0 R/Rect[280.5 810 314.5 842]/Subtype/Widget/T(sig)/V 12 0 R>>
endobj

...

I notice the third page changed, it has an annots(object 13). Now, i want modify itext code to add /Widget for each page but using same /AP and /V.Then there have same signature graphic in each page but only add signature once. like ...

4 0 obj
<</Annots[13 0 R]/Contents 5 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj
7 0 obj
<</Annots[14 0 R]/Contents 8 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj
9 0 obj
<</Annots[15 0 R]/Contents 10 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj
13 0 obj
<</AP<</N 18 0 R>>/F 132/FT/Sig/P 4 0 R/Rect[280.5 810 314.5 842]/Subtype/Widget/T(sig)/V 12 0 R>>
endobj
14 0 obj
<</AP<</N 18 0 R>>/F 132/FT/Sig/P 7 0 R/Rect[200 400 300 420]/Subtype/Widget/T(sig)/V 12 0 R>>
endobj
15 0 obj
<</AP<</N 18 0 R>>/F 132/FT/Sig/P 9 0 R/Rect[100 200 150 480]/Subtype/Widget/T(sig)/V 12 0 R>>
endobj
11 0 obj
<</Fields[13 0 R 14 0 R 15 0 R]/SigFlags 3>>
endobj

... I don't know if the example fits. I've read about it before, What I want is a signature with a different /Rect signature graphic on each page after a signature.

  1. How can i do that using iText7 Java?
  2. Can add such a signature multiple times to a PDF and pass signature verification?
  3. After doing so, can Signature ArcoForm and field be deleted and/widgets cleared?
  4. Can I crop Signature Graphic to show different parts on different pages?

Here's some code:

PdfDocument pdfDocument = new PdfDocument(new PdfReader(FILE));
final int pageCount = pdfDocument.getNumberOfPages();
pdfDocument.close();

PdfReader pdfReader = new PdfReader(FILE);
PdfSigner pdfSigner = new PdfSigner(pdfReader, new FileOutputStream(SIGN), new StampingProperties().useAppendMode());

File imageFile = new File(IMAGE);
java.awt.Image image = ImageIO.read(imageFile);
ImageData imageData = ImageDataFactory.create(image, null);
Rectangle rect = new Rectangle(
    (pdfDocument.getDefaultPageSize().getRight() / 2) - (imageData.getWidth() / 2),
    pdfDocument.getDefaultPageSize().getTop() - imageData.getHeight(),
    imageData.getWidth(),
    imageData.getHeight()
);

PdfSignatureAppearance appearance = pdfSigner.getSignatureAppearance();
appearance.setPageNumber(pageCount);
appearance.setSignatureGraphic(imageData);
appearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);
appearance.setPageRect(rect);
appearance.setReason("reason");
appearance.setLocation("location");
appearance.setReuseAppearance(false);

pdfSigner.setFieldName("sig");

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);

BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);

IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, provider.getName());
IExternalDigest digest = new BouncyCastleDigest();

pdfSigner.signDetached(digest, pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CMS);

append:

In com.itextpdf.signatures.PdfSigner.preClose() method, i tried the following code, although successfully adding the desired object, but only the widget annotations that are added first can be shown in Adobe Reader, what should I do? the PDF I got

if (fieldExist) ... else {
    PdfDictionary ap = new PdfDictionary();
    for (int i = 1; i <= document.getNumberOfPages(); i++) {
        PdfWidgetAnnotation widget = new PdfWidgetAnnotation(appearance.getPageRect());
        widget.setFlags(PdfAnnotation.PRINT | PdfAnnotation.LOCKED);

        PdfSignatureFormField sigField = PdfFormField.createSignature(document);
        sigField.setFieldName(name);
        sigField.put(PdfName.V, cryptoDictionary.getPdfObject());
        sigField.addKid(widget);

        if (this.fieldLock != null) {
            this.fieldLock.getPdfObject().makeIndirect(document);
            sigField.put(PdfName.Lock, this.fieldLock.getPdfObject());
            fieldLock = this.fieldLock;
        }

        widget.setPage(document.getPage(i));
        widget.put(PdfName.AP, ap);
        if (1 == i)
            ap.put(PdfName.N, appearance.getAppearance().getPdfObject());

        acroForm.addField(sigField, document.getPage(i));
    }
    
    ...
    
}
Yinxf
  • 57
  • 4
  • In your *"like ..."* you have three AcroForm signature field objects with a merged widget annotation each, sharing the same field name. Thus, those three objects represent three widgets of the same abstract signature form field. But since ISO 32000-2 signature form fields may not have more than one widget. Thus, your construct strictly speaking is invalid. Do you really want that? – mkl Nov 15 '20 at 14:30
  • When I modified the code to implement this behavior, I found that although the object was successfully added, it could not all be displayed on the Adobe Reader because the three fields had the same name.Please look at the supplement. How can I fix it? – Yinxf Nov 15 '20 at 15:11
  • *"it could not all be displayed on the Adobe Reader because the three fields had the same name.Please look at the supplement. How can I fix it?"* - Well, as using the same name also causes other issues, see my first comment, a fix would be to use different names. – mkl Nov 15 '20 at 15:28
  • I made a mistake right from the start, in fact what I really wanted was to generate an AcroForm Signature Field at a time, but add a widget annotation per page.Can it be done?I notice that the /P objects using the TreeMap index puts the same Key in overrides. – Yinxf Nov 16 '20 at 01:08
  • You mean one field with multiple widgets? In that case see my first comment, *signature form fields may not have more than one widget*. Or do I misread you? – mkl Nov 16 '20 at 08:31
  • Yes, one field with multiple widgets.The code forbids this.If I break the rules, can The reader display widgets as I want?I don't know if there are any other pitfalls. – Yinxf Nov 16 '20 at 12:17
  • 1
    If you break the rules, you produce invalid PDF. Current Adobe Acrobat versions probably will still accept them but there is no guarantee they will continue to do so. (Adobe has been telling people for over a decade now that signature fields shall not have more than one widget, so no one should be surprised if they start enforcing that.) Furthermore, there are other PDF signature validators which already nowadays may protest. – mkl Nov 16 '20 at 15:47

0 Answers0