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.
- How can i do that using iText7 Java?
- Can add such a signature multiple times to a PDF and pass signature verification?
- After doing so, can Signature ArcoForm and field be deleted and/widgets cleared?
- 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));
}
...
}