/** * <a href="http://itext.2136553.n4.nabble.com/trying-to-remove-a-signature-from-pdf-file-tt4660983.html"> * trying to remove a signature from pdf file * </a> * <br/> * <a href="http://itext.2136553.n4.nabble.com/attachment/4660983/0/PDFSignedFirmaCerta.pdf"> * PDFSignedFirmaCerta.pdf * </a> * <p> * Indeed, this code fails with a {@link NullPointerException}. The cause is that a dubious construct * created by the signature software then is processed by iText code not sufficiently defensively programmed: * The signature claims to have an annotation on a page but that page does claim not to have any anotations * at all. * </p> */ @Test public void testRemoveSignatureFromPDFSignedFirmaCerta() throws IOException, GeneralSecurityException, DocumentException { try ( InputStream inputStream = getClass().getResourceAsStream("PDFSignedFirmaCerta.pdf"); OutputStream outputStream = new FileOutputStream(new File(RESULT_FOLDER, "PDFSignedFirmaCerta-withoutSig.pdf"))) { Provider provider = new BouncyCastleProvider(); Security.addProvider(provider); PdfReader reader = new PdfReader(inputStream, null); AcroFields af = reader.getAcroFields(); ArrayList<String> names = af.getSignatureNames(); for (String name : names) { System.out.println("Signature name: " + name); System.out.println("Signature covers whole document: " + af.signatureCoversWholeDocument(name)); PdfPKCS7 pk = af.verifySignature(name, provider.getName()); System.out.println("SignatureDate: " + pk.getSignDate()); System.out.println("Certificate: " + pk.getSigningCertificate()); System.out.println("Document modified: " + !pk.verify()); af.removeField(name); } PdfStamper stamper = new PdfStamper(reader, outputStream, '\0'); stamper.close(); } }
private int numberOfVisibleSignatureFieldsOnSignaturePage(AcroFields readerFields, ArrayList<String> signatureFieldsNames, int signaturePage) { int count = 0; for (String signatureFieldName : signatureFieldsNames) { Item i = readerFields.getFieldItem(signatureFieldName); int page = i.getPage(0); if(page == signaturePage){ PdfDictionary pdct = i.getMerged(0); PdfNumber flags = pdct.getAsNumber(PdfName.F); if ((flags.intValue() & PdfAnnotation.FLAGS_HIDDEN) == 0) { count = count + 1; } } } return count; }
/** * <a href="https://stackoverflow.com/questions/46730760/no-fields-were-printed-on-console-after-verifying-if-form-is-using-acroform-or-x"> * No fields were printed on console after verifying if form is using Acroform or XFA technology? * </a> * <br/> * <a href="http://blogs.adobe.com/formfeed/files/formfeed/Samples/multiview.pdf"> * multiview.pdf * </a> * from * <a href="http://blogs.adobe.com/formfeed/2011/02/multiple-top-level-subforms.html"> * Multiple Top Level Subforms * </a> * <p> * The OP's observation can be reproduced using this sample PDF. * </p> */ @Test public void testReadFieldsFromMultiview() throws IOException { try ( InputStream resource = getClass().getResourceAsStream("multiview.pdf") ) { PdfReader reader = new PdfReader(resource); AcroFields form = reader.getAcroFields(); XfaForm xfa = form.getXfa(); System.out.println(xfa.isXfaPresent() ? "XFA form" : "AcroForm"); Set<String> fields = form.getFields().keySet(); for (String key : fields) { System.out.println(key); } System.out.flush(); System.out.close(); reader.close(); } }
/** * <a href="http://stackoverflow.com/questions/37726215/why-does-my-signature-revision-number-increment-by-2-in-itext-after-detached-s"> * Why does my signature revision number increment by 2 (in itext) after detached signing? * </a> * <br/> * <a href="https://onedrive.live.com/redir?resid=2F03BFDA84B77A41!113&authkey=!ABPGZ7pxuxoE8A0&ithint=file%2Cpdf"> * signedoutput.pdf * </a> * <p> * The issue cannot be reproduced. In particular the PDF contains only a single revision. * </p> */ @Test public void testVerifySignedOutput() throws IOException, GeneralSecurityException { System.out.println("\n\nsignedoutput.pdf\n================"); try ( InputStream resource = getClass().getResourceAsStream("signedoutput.pdf") ) { PdfReader reader = new PdfReader(resource); AcroFields acroFields = reader.getAcroFields(); List<String> names = acroFields.getSignatureNames(); for (String name : names) { System.out.println("Signature name: " + name); System.out.println("Signature covers whole document: " + acroFields.signatureCoversWholeDocument(name)); System.out.println("Document revision: " + acroFields.getRevision(name) + " of " + acroFields.getTotalRevisions()); PdfPKCS7 pk = acroFields.verifySignature(name); System.out.println("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate())); System.out.println("Document verifies: " + pk.verify()); } } System.out.println(); }
/** * <a href="http://stackoverflow.com/questions/42824577/itext-can-not-verify-signed-pdf-docs-edited-by-nitro-pro-10-11"> * itext can not verify signed pdf docs edited by nitro pro 10/11 * </a> * <br/> * <a href="https://alimail.fadada.com/signed.pdf"> * babylove_signed.pdf * </a> * <p> * Validation correctly shows verification success for a single * signature that does cover the whole document. * </p> */ @Test public void testVerifyBabyloveSigned() throws IOException, GeneralSecurityException { System.out.println("\n\nbabylove_signed.pdf\n==================="); try ( InputStream resource = getClass().getResourceAsStream("babylove_signed.pdf") ) { PdfReader reader = new PdfReader(resource); AcroFields acroFields = reader.getAcroFields(); List<String> names = acroFields.getSignatureNames(); for (String name : names) { System.out.println("Signature name: " + name); System.out.println("Signature covers whole document: " + acroFields.signatureCoversWholeDocument(name)); System.out.println("Document revision: " + acroFields.getRevision(name) + " of " + acroFields.getTotalRevisions()); PdfPKCS7 pk = acroFields.verifySignature(name); System.out.println("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate())); System.out.println("Document verifies: " + pk.verify()); } } System.out.println(); }
/** * <a href="http://stackoverflow.com/questions/42824577/itext-can-not-verify-signed-pdf-docs-edited-by-nitro-pro-10-11"> * itext can not verify signed pdf docs edited by nitro pro 10/11 * </a> * <br/> * <a href="https://alimail.fadada.com/signed&modify_by_nitro.pdf"> * babylove_signed&modify_by_nitro.pdf * </a> * <p> * Validation correctly shows verification success for a single * signature that does <b>not</b> cover the whole document. * </p> */ @Test public void testVerifyBabyloveSignedAndModifyByNitro() throws IOException, GeneralSecurityException { System.out.println("\n\nbabylove_signed&modify_by_nitro.pdf\n==================="); try ( InputStream resource = getClass().getResourceAsStream("babylove_signed&modify_by_nitro.pdf") ) { PdfReader reader = new PdfReader(resource); AcroFields acroFields = reader.getAcroFields(); List<String> names = acroFields.getSignatureNames(); for (String name : names) { System.out.println("Signature name: " + name); System.out.println("Signature covers whole document: " + acroFields.signatureCoversWholeDocument(name)); System.out.println("Document revision: " + acroFields.getRevision(name) + " of " + acroFields.getTotalRevisions()); PdfPKCS7 pk = acroFields.verifySignature(name); System.out.println("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate())); System.out.println("Document verifies: " + pk.verify()); } } System.out.println(); }
/** * <a href="https://stackoverflow.com/questions/45027712/invalid-signature-when-signing-an-existing-sigrature-field-with-cosign-sapi"> * Invalid signature when signing an existing sigrature field with CoSign SAPI * </a> * <br/> * <a href="https://www.dropbox.com/s/j6eme53lleaok13/test_signed.pdf?dl=0"> * test_signed-1.pdf * </a> * <p> * Validation shows verification success while both Adobe and SD DSS fail. * Embedded certificates have issues (emailAddress RDN is typed PrintableString * which is wrong - specified is IA5String - and does not even make sense as * there is no '@' in PrintableString), but does this explain it? * </p> */ @Test public void testVerifyTestSigned1() throws IOException, GeneralSecurityException { System.out.println("\n\ntest_signed-1.pdf\n==================="); try ( InputStream resource = getClass().getResourceAsStream("test_signed-1.pdf") ) { PdfReader reader = new PdfReader(resource); AcroFields acroFields = reader.getAcroFields(); List<String> names = acroFields.getSignatureNames(); for (String name : names) { System.out.println("Signature name: " + name); System.out.println("Signature covers whole document: " + acroFields.signatureCoversWholeDocument(name)); System.out.println("Document revision: " + acroFields.getRevision(name) + " of " + acroFields.getTotalRevisions()); PdfPKCS7 pk = acroFields.verifySignature(name); System.out.println("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate())); System.out.println("Document verifies: " + pk.verify()); } } System.out.println(); }
/** * <a href="https://stackoverflow.com/questions/46346144/digital-signature-verification-with-itext-not-working"> * Digital Signature Verification with itext not working * </a> * <br/> * <a href="https://drive.google.com/open?id=0B1XKjvoeoyPZWnk5bzc5T3VSQUk"> * test_dsp.pdf * </a> * <p> * The issue is that the signature uses ECDSA and iText 5 does not (yet) * support ECDSA. "Support" here actually means that iText cannot find * the name ECDSA for the OID 1.2.840.10045.4.3.2 (SHA256withECDSA) to * build a proper algorithm name to use for verification. * </p> * <p> * Adding a mapping "1.2.840.10045.4.3.2" to "ECDSA" resolves the issue. * </p> * @see #testVerify20180115an_signed_original() */ @Test public void testVerifyTestDsp() throws IOException, GeneralSecurityException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { Field algorithmNamesField = EncryptionAlgorithms.class.getDeclaredField("algorithmNames"); algorithmNamesField.setAccessible(true); @SuppressWarnings("unchecked") HashMap<String, String> algorithmNames = (HashMap<String, String>) algorithmNamesField.get(null); algorithmNames.put("1.2.840.10045.4.3.2", "ECDSA"); System.out.println("\n\ntest_dsp.pdf\n==================="); try ( InputStream resource = getClass().getResourceAsStream("test_dsp.pdf") ) { PdfReader reader = new PdfReader(resource); AcroFields acroFields = reader.getAcroFields(); List<String> names = acroFields.getSignatureNames(); for (String name : names) { System.out.println("Signature name: " + name); System.out.println("Signature covers whole document: " + acroFields.signatureCoversWholeDocument(name)); System.out.println("Document revision: " + acroFields.getRevision(name) + " of " + acroFields.getTotalRevisions()); PdfPKCS7 pk = acroFields.verifySignature(name); System.out.println("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate())); System.out.println("Document verifies: " + pk.verify()); } } System.out.println(); }
/** * <a href="https://stackoverflow.com/questions/48285453/verifying-certificate-of-signed-and-secured-pdf-in-itext-pdf-java"> * Verifying certificate of signed and secured PDF in iText PDF Java * </a> * <br/> * <a href="https://drive.google.com/drive/folders/1KAqHUh-Iij0I4WXJUCx-rMd8FQFq5tCe?usp=sharing"> * pdf-sample-signed.pdf * </a> * <p> * The PDF is both signed and encrypted. Apparently iText "decrypts" the * values of the <b>Contents</b> key in signature dictionaries even though * this is an explicit exception. The parsing of this "decrypted" signature * container obviously fails. * </p> */ @Test public void testVerifyPdfSampleSigned() throws IOException, GeneralSecurityException { System.out.println("\n\npdf-sample-signed.pdf\n==================="); try ( InputStream resource = getClass().getResourceAsStream("pdf-sample-signed.pdf") ) { PdfReader reader = new PdfReader(resource, "password".getBytes()); AcroFields acroFields = reader.getAcroFields(); List<String> names = acroFields.getSignatureNames(); for (String name : names) { System.out.println("Signature name: " + name); System.out.println("Signature covers whole document: " + acroFields.signatureCoversWholeDocument(name)); System.out.println("Document revision: " + acroFields.getRevision(name) + " of " + acroFields.getTotalRevisions()); PdfPKCS7 pk = acroFields.verifySignature(name); System.out.println("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate())); System.out.println("Document verifies: " + pk.verify()); } } System.out.println(); }
/** * <a href="https://stackoverflow.com/questions/48211757/itext-pdf-timestamp-validation-returns-false-why"> * iText pdf timestamp validation returns false, why? * </a> * <br/> * <a href="https://drive.google.com/file/d/1skI3NM9cqw2m6eW9jKXaJXKzvCjyQMib/view"> * testpdf_timestamp.pdf * </a> * <p> * The code the OP used for inspiration was for retrieving information * from a signature which may include a signature time stamp. The PDF * of the OP, on the other hand, contains a document time stamp. The * call `pkcs7.verifyTimestampImprint()` checks the time stamp as a * signature time stamp and, therefore, fails. * </p> */ @Test public void testDocumentTimestampLikeRadekKantor() throws IOException, GeneralSecurityException { try ( InputStream resource = getClass().getResourceAsStream("testpdf_timestamp.pdf") ) { PdfReader reader = new PdfReader(resource); AcroFields fields = reader.getAcroFields(); ArrayList<String> names = fields.getSignatureNames(); for (String name : names) { System.out.println("===== " + name + " ====="); System.out.println("Signature covers whole document: " + fields.signatureCoversWholeDocument(name)); System.out.println("Document revision: " + fields.getRevision(name) + " of " + fields.getTotalRevisions()); PdfPKCS7 pkcs7 = fields.verifySignature(name); System.out.println("Integrity check OK? " + pkcs7.verify()); SimpleDateFormat date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS"); System.out.println("Signed on: " + date_format.format(pkcs7.getSignDate().getTime())); if (pkcs7.getTimeStampDate() != null) { System.out.println("TimeStamp: " + date_format.format(pkcs7.getTimeStampDate().getTime())); TimeStampToken ts = pkcs7.getTimeStampToken(); System.out.println("TimeStamp service: " + ts.getTimeStampInfo().getTsa()); // Why pkcs7.verifyTimestampImprint() returns FLASE? System.out.println("Timestamp verified? " + pkcs7.verifyTimestampImprint()); } } } }
public static void addImage(byte[] input, OutputStream output, Image image, String placeholder) throws IOException, DocumentException { try (PdfReaderAutoclosable pdfReader = new PdfReaderAutoclosable(input); PdfStamperAutoclosable pdfStamper = new PdfStamperAutoclosable(pdfReader, output)) { AcroFields form = pdfStamper.getAcroFields(); List<AcroFields.FieldPosition> positions = form.getFieldPositions(placeholder); positions.forEach(p -> { image.scaleToFit(p.position.getWidth(), p.position.getHeight()); image.setAbsolutePosition(p.position.getLeft() + (p.position.getWidth() - image.getScaledWidth()) / 2, p.position.getBottom() + (p.position.getHeight() - image.getScaledHeight()) / 2); PdfContentByte cb = pdfStamper.getOverContent(p.page); try { cb.addImage(image); } catch(DocumentException e) { throw Throwables.propagate(e); } }); } }
/** * <a href="http://stackoverflow.com/questions/42819618/itext-fill-checkbox-with-value"> * itext fill checkbox with value * </a> * <br/> * <a href="https://www.poreskaupravars.org/Documents/Doc/PD3100.pdf"> * PD3100.pdf * </a> * <p> * This test uses a valid name and so at least creates * a PDF displayed with a somehow selected field. * </p> * @see #testPd3100SetVrPr4ToNoAppend() */ @Test public void testPd3100SetVrPr4ToNo() throws IOException, DocumentException { try ( InputStream resource = getClass().getResourceAsStream("PD3100.pdf"); OutputStream result = new FileOutputStream(new File(RESULT_FOLDER, "PD3100-SetVrPr4ToNo.pdf")) ) { PdfReader pdfReader = new PdfReader(resource); PdfStamper pdfStamper = new PdfStamper(pdfReader, result, (char)0, false); AcroFields acroFields = pdfStamper.getAcroFields(); System.out.println("Available values for VrPr4: " + Arrays.asList(acroFields.getAppearanceStates("VrPr4"))); acroFields.setField("VrPr4", "No"); pdfStamper.close(); } }
/** * <a href="http://stackoverflow.com/questions/39450688/itext-pdf-checkboxon-off-not-appearing-for-some-pdf"> * IText Pdf - Checkbox(On/Off) not appearing for some pdf * </a> * <br/> * <a href="http://www.filedropper.com/pdfexample_1"> * PDF example.pdf * </a> * <p> * The observations of the OP cannot be reproduced. * </p> */ @Test public void testShowPdfExampleStates() throws IOException { String resourceName = "PDF example.pdf"; try ( InputStream resource = getClass().getResourceAsStream(resourceName) ) { PdfReader reader = new PdfReader(resource); AcroFields form = reader.getAcroFields(); String[] values = form.getAppearanceStates("claimsType"); System.out.printf("\n%s\nThe appearance states of claimsType are %s.\n", resourceName, Arrays.asList(values)); } }
/** * <a href="http://stackoverflow.com/questions/39450688/itext-pdf-checkboxon-off-not-appearing-for-some-pdf"> * IText Pdf - Checkbox(On/Off) not appearing for some pdf * </a> * <br/> * <a href="http://www.filedropper.com/pdftest2"> * PDF test 2.pdf * </a> * <p> * The observations of the OP cannot be reproduced. * </p> */ @Test public void testShowPdfTest2States() throws IOException { String resourceName = "PDF test 2.pdf"; try ( InputStream resource = getClass().getResourceAsStream(resourceName) ) { PdfReader reader = new PdfReader(resource); AcroFields form = reader.getAcroFields(); String[] values = form.getAppearanceStates("claimsType"); System.out.printf("\n%s\nThe appearance states of claimsType are %s.\n", resourceName, Arrays.asList(values)); } }
/** * <a href="http://stackoverflow.com/questions/28967737/itextsharp-setfield-for-fields-with-same-name-on-different-pages"> * iTextSharp SetField for fields with same name on different pages * </a> * <p> * Reproducing the issue with iText * </p> */ @Test public void testFillInForm() throws IOException, DocumentException { try ( InputStream resource = getClass().getResourceAsStream("ING_bewindvoering_regelen_tcm162-49609.pdf"); OutputStream result = new FileOutputStream(new File(RESULT_FOLDER, "hybrid-form-fillin.pdf")) ) { PdfReader reader = new PdfReader(resource); PdfStamper stamper = new PdfStamper(reader, result); AcroFields fields = stamper.getAcroFields(); fields.setField("topmostSubform[0].CheckBox2A[0]", "1"); // fields.setField("topmostSubform[0].Page2[0].CheckBox2A[0]", "1"); stamper.close(); } }
void setFields(File result, String value) throws IOException, DocumentException { try ( InputStream resource = getClass().getResourceAsStream("RichTextDoc.pdf") ) { PdfReader reader = new PdfReader(resource); PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(result)); AcroFields fields = stamper.getAcroFields(); fields.setGenerateAppearances(false); Assert.assertFalse("Setting rich text to normal field should fail", fields.setFieldRichValue("NormalText", value)); Assert.assertTrue("Setting rich text to rich text field should succeed", fields.setFieldRichValue("RichText", value)); stamper.close(); } }
/** * <a href="http://stackoverflow.com/questions/37027579/how-to-associate-a-previous-signature-in-a-new-signature-field"> * How to associate a previous signature in a new signature field * </a> * <br/> * <span>BLANK-signed.pdf, <em>a blank file from elsewhere with an invisible signature.</em></span> * <p> * Quite surprisingly it turns out that changing the signature appearance is possible without * breaking the signature, merely a warning appears which can be hidden by simply signing again. * </p> */ @Test public void testChangeAppearances() throws IOException, DocumentException { try ( InputStream resource = getClass().getResourceAsStream("BLANK-signed.pdf"); OutputStream result = new FileOutputStream(new File(RESULT_FOLDER, "BLANK-signed-app.pdf"))) { PdfReader pdfReader = new PdfReader(resource); PdfStamper pdfStamper = new PdfStamper(pdfReader, result, '\0', true); AcroFields acroFields = pdfStamper.getAcroFields(); for (String signatureName : acroFields.getSignatureNames()) { Item field = acroFields.getFieldItem(signatureName); field.writeToAll(PdfName.RECT, new PdfArray(new int[]{100,100,200,200}), Item.WRITE_WIDGET); field.markUsed(acroFields, Item.WRITE_WIDGET); PdfAppearance appearance = PdfAppearance.createAppearance(pdfStamper.getWriter(), 100, 100); appearance.setColorStroke(BaseColor.RED); appearance.moveTo(0, 0); appearance.lineTo(99, 99); appearance.moveTo(0, 99); appearance.lineTo(99, 0); appearance.stroke(); PdfDictionary appDict = new PdfDictionary(); appDict.put(PdfName.N, appearance.getIndirectReference()); field.writeToAll(PdfName.AP, appDict, Item.WRITE_WIDGET); } pdfStamper.close(); } }
/** * <a href="https://github.com/itext/itextpdf/pull/36"> * Adding Support for OID 1.2.840.113549.1.1.10 #36 * </a> * <br/> * <a href="https://github.com/itext/itextpdf/files/1641593/2018.01.15.an_signed_original.pdf"> * 2018.01.15.an_signed_original.pdf * </a> * <p> * Support for RSASSA-PSS can also be injected using reflection as done here. * </p> * @see #testVerifyTestDsp() */ @Test public void testVerify20180115an_signed_original() throws IOException, GeneralSecurityException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { Field algorithmNamesField = EncryptionAlgorithms.class.getDeclaredField("algorithmNames"); algorithmNamesField.setAccessible(true); @SuppressWarnings("unchecked") HashMap<String, String> algorithmNames = (HashMap<String, String>) algorithmNamesField.get(null); algorithmNames.put("1.2.840.113549.1.1.10", "RSAandMGF1"); System.out.println("\n\n2018.01.15.an_signed_original.pdf\n==================="); try ( InputStream resource = getClass().getResourceAsStream("2018.01.15.an_signed_original.pdf") ) { PdfReader reader = new PdfReader(resource); AcroFields acroFields = reader.getAcroFields(); List<String> names = acroFields.getSignatureNames(); for (String name : names) { System.out.println("Signature name: " + name); System.out.println("Signature covers whole document: " + acroFields.signatureCoversWholeDocument(name)); System.out.println("Document revision: " + acroFields.getRevision(name) + " of " + acroFields.getTotalRevisions()); PdfPKCS7 pk = acroFields.verifySignature(name); System.out.println("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate())); System.out.println("Document verifies: " + pk.verify()); } } System.out.println(); }
/** * <a href="http://stackoverflow.com/questions/32332490/new-signature-field-rotated-90-degrees"> * New Signature Field Rotated 90 Degrees * </a> * <br/> * <a href="https://drive.google.com/open?id=0B3pKBz-WDrXnM3hYeDFtXzhldnM"> * DA3161-Template.pdf * </a> * <p> * The page in your document is rotated using the Rotate page dictionary entry. * When creating a field to be filled-in by others later, you have to add a hint * to the field indicating a counter-rotation if you want the field content to * effectively appear upright. * </p> * <p> * You do this by setting the MKRotation attribute of the field. This creates a * rotation entry R with value 90 in the appearance characteristics dictionary * MK of the field. * </p> */ @Test public void testDA3161_Template() throws IOException, GeneralSecurityException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, DocumentException { try ( InputStream resource = getClass().getResourceAsStream("DA3161-Template.pdf"); OutputStream result = new FileOutputStream(new File(RESULT_FOLDER, "DA3161-Template_Field.pdf")) ) { System.out.println("DA3161-Template.pdf"); PdfReader reader = new PdfReader(resource); PdfStamper pdfStamper = new PdfStamper(reader, result); AcroFields fields = pdfStamper.getAcroFields(); int itemno = 3; //Get location to the field where we will place the signature field FieldPosition NewPosition = fields.getFieldPositions("DESC_0_" + (itemno + 1)).get(0); float l1 = NewPosition.position.getLeft(); float r1 = NewPosition.position.getRight(); float t1 = NewPosition.position.getTop(); float b1 = NewPosition.position.getBottom(); PdfFormField field = PdfFormField.createSignature(pdfStamper.getWriter()); field.setFieldName("G4_SignatureX"); // Set the widget properties field.setWidget(new Rectangle(r1, t1, l1, b1), PdfAnnotation.HIGHLIGHT_NONE); field.setFlags(PdfAnnotation.FLAGS_PRINT); // !!!!!!!!!!!!!!!!!!! field.setMKRotation(90); // Add the annotation pdfStamper.addAnnotation(field, 1); pdfStamper.close(); } }
public static void fillOutForm(byte[] input, OutputStream output, Map<String, Object> values) throws IOException, DocumentException { try (PdfReaderAutoclosable pdfReader = new PdfReaderAutoclosable(input); PdfStamperAutoclosable stamper = new PdfStamperAutoclosable(pdfReader, output)) { stamper.setFormFlattening(true); AcroFields fields = stamper.getAcroFields(); values.forEach((k, v) -> { if(v instanceof Boolean) setField(fields, k, (Boolean) v); else setField(fields, k, v); }); } }
private static void setField(AcroFields fields, String key, String value) { try { fields.setField(key, value); } catch(DocumentException | IOException e) { throw new RuntimeException("Error setting PDF field", e); } }
/** * When the "signable" aspect is applied, extract the signature fields and add them * to the multivalue property */ public void onAddAspect(NodeRef nodeRef, QName aspectTypeQName) { try { // when the aspect is added, extract the signature fields from the PDF ArrayList<String> signatureFields = new ArrayList<String>(); ContentReader pdfReader = serviceRegistry.getContentService().getReader(nodeRef, ContentModel.PROP_CONTENT); PdfReader reader = new PdfReader(pdfReader.getContentInputStream()); AcroFields form = reader.getAcroFields(); Map<String, Item> fields = form.getFields(); Iterator<String> it = fields.keySet().iterator(); while(it.hasNext()) { String fieldName = it.next(); if(form.getFieldType(fieldName) == AcroFields.FIELD_TYPE_SIGNATURE) { // add this signature field to the list of available fields signatureFields.add(fieldName); } } serviceRegistry.getNodeService().setProperty(nodeRef, CounterSignSignatureModel.PROP_SIGNATUREFIELDS, signatureFields); } catch(IOException ex) { logger.error("Error extracting PDF signature fields from document: " + ex); } }
/** * This method extracts integrated signature information from the PDF * this class is instantiated with. * @return */ //@SuppressWarnings("unchecked") public Map<String, SignatureData> extractSignatures() { final Map<String, SignatureData> result = new HashMap<String, SignatureData>(); final AcroFields fields = reader.getAcroFields(); for (String name: fields.getSignatureNames()) { PdfDictionary sigDict = fields.getSignatureDictionary(name); PdfString contents = sigDict.getAsString(PdfName.CONTENTS); PdfName subFilter = sigDict.getAsName(PdfName.SUBFILTER); if (contents != null) { byte[] contentBytes = contents.getOriginalBytes(); byte[] containerBytes = null; /* ContentInfo contentInfo = null; try { contentInfo = new ContentInfoImpl(contentBytes); byte[] bytes = contentInfo.getEncoded(); if (bytes.length <= contentBytes.length) { boolean equal = true; for (int i = 0; i < bytes.length; i++) { if (bytes[i] != contentBytes[i]) { System.err.println("Re-encoded differs at " + i); equal = false; break; } } if (equal) containerBytes = bytes; } else { System.err.println("Re-encoded data too long"); } } catch (GeneralSecurityException e) { System.err.println("Failure decoding content as container."); e.printStackTrace(); } */ Date signingTime = null; Object pdfDateEntry = sigDict.get(PdfName.M); if (pdfDateEntry != null) { Calendar cal = PdfDate.decode(pdfDateEntry.toString()); if (cal != null) { signingTime = cal.getTime(); } } result.put(name, new SignatureData(/*contentInfo,*/ containerBytes, contentBytes, subFilter, signingTime)); } } return result; }
/** * <a href="http://stackoverflow.com/questions/35134568/itext-ltv-enabled-how-to-add-more-crls"> * iText LTV enabled - how to add more CRLs? * </a> * <p> * The original addLtv method of the OP modified merely to allow the * source PDF to be given as {@link InputStream} instead of {@link String}. * </p> */ public void addLtvJanPokorny(InputStream src, String dest) throws IOException, DocumentException, GeneralSecurityException { PdfReader r = new PdfReader(src); FileOutputStream fos = new FileOutputStream(dest); PdfStamper stp = new PdfStamper(r, fos, '\0', true); LtvVerification v = stp.getLtvVerification(); AcroFields fields = stp.getAcroFields(); ArrayList<String> names = fields.getSignatureNames(); String sigName = names.get(names.size() - 1); System.out.println("found signature: " + sigName); PdfPKCS7 pkcs7 = fields.verifySignature(sigName); //add LTV OcspClient ocsp = new OcspClientBouncyCastle(); CrlClient crlClient1 = new CrlClientOnline("http://www.postsignum.cz/crl/psrootqca2.crl"); ArrayList<CrlClient> crllist = new ArrayList<CrlClient>(); crllist.add(crlClient1); CrlClient crlClient2 = new CrlClientOnline("http://www.postsignum.cz/crl/pspublicca2.crl"); crllist.add(crlClient2); System.out.println("crllist.size=" + crllist.size()); if (pkcs7.isTsp()) { for (CrlClient crlclient : crllist) { if (v.addVerification(sigName, new OcspClientBouncyCastle(), crlclient, LtvVerification.CertificateOption.SIGNING_CERTIFICATE, LtvVerification.Level.CRL, LtvVerification.CertificateInclusion.NO)) { System.out.println("crl " + crlclient.toString() + " added to timestamp"); } } } else { for (String name : names) { for (int i = 0; i < crllist.size(); i++) { if (v.addVerification(name, ocsp, crllist.get(i), LtvVerification.CertificateOption.WHOLE_CHAIN, LtvVerification.Level.CRL, LtvVerification.CertificateInclusion.NO)) { System.out.println("crl " + crllist.get(i).toString() + " added to " + name); } if (i > 0) { System.out.println("found verification, merge"); v.merge(); } } } } stp.close(); }
/** * <a href="http://stackoverflow.com/questions/35134568/itext-ltv-enabled-how-to-add-more-crls"> * iText LTV enabled - how to add more CRLs? * </a> * <p> * The original addLtv method of the OP modified to allow the source PDF * to be given as {@link InputStream} instead of {@link String} and fixed * to properly use multiple CRLs. * </p> */ public void addLtvFixed(InputStream src, String dest) throws IOException, DocumentException, GeneralSecurityException { PdfReader r = new PdfReader(src); FileOutputStream fos = new FileOutputStream(dest); PdfStamper stp = new PdfStamper(r, fos, '\0', true); LtvVerification v = stp.getLtvVerification(); AcroFields fields = stp.getAcroFields(); ArrayList<String> names = fields.getSignatureNames(); String sigName = names.get(names.size() - 1); System.out.println("found signature: " + sigName); PdfPKCS7 pkcs7 = fields.verifySignature(sigName); //add LTV OcspClient ocsp = new OcspClientBouncyCastle(); CrlClient crlClient = new CrlClientOnline("http://www.postsignum.cz/crl/psrootqca2.crl", "http://www.postsignum.cz/crl/pspublicca2.crl"); if (pkcs7.isTsp()) { if (v.addVerification(sigName, new OcspClientBouncyCastle(), crlClient, LtvVerification.CertificateOption.SIGNING_CERTIFICATE, LtvVerification.Level.CRL, LtvVerification.CertificateInclusion.NO)) { System.out.println("crl " + crlClient.toString() + " added to timestamp"); } } else { for (String name : names) { if (v.addVerification(name, ocsp, crlClient, LtvVerification.CertificateOption.WHOLE_CHAIN, LtvVerification.Level.CRL, LtvVerification.CertificateInclusion.NO)) { System.out.println("crl " + crlClient.toString() + " added to " + name); } } } stp.close(); }
@Override protected Void doInBackground(Uri... params) { try { PdfReader reader = new PdfReader(ctx.getContentResolver().openInputStream(params[0])); try { AcroFields acroFields = reader.getAcroFields(); List<String> names = acroFields.getBlankSignatureNames(); for(String name : names) { List<String> pages = new LinkedList<String>(); for (AcroFields.FieldPosition fp : acroFields.getFieldPositions(name)) { pages.add(Integer.toString(fp.page)); } publishProgress(new Signature(name, pages)); } /* names = acroFields.getSignatureNames(); for(String name : names) { List<String> pages = new LinkedList<String>(); for(AcroFields.FieldPosition fp : acroFields.getFieldPositions(name)) { pages.add(Integer.toString(fp.page)); } String signer = ""; PdfPKCS7 pkcs7 = acroFields.verifySignature(name); X509Certificate cert = pkcs7.getSigningCertificate(); if (cert != null) { X500Name subject = JcaX500NameUtil.getSubject(cert); RDN[] subjectCNs = subject.getRDNs(BCStyle.CN); if (subjectCNs.length > 0) signer = IETFUtils.valueToString(subjectCNs[0].getFirst().getValue()); } publishProgress(new Signature(name, pages, true, signer)); } */ return null; } finally { reader.close(); } } catch (IOException ioe) { Log.e(TAG, "Failed to parse pdf"); return null; } }
private static void setField(AcroFields fields, String key, Object value) { setField(fields, key, value.toString()); }
private static void setField(AcroFields fields, String key, Boolean value) { String[] states = fields.getAppearanceStates(key); if(states.length > 0) setField(fields, key, states.length > 1 ? states[value.booleanValue() ? 1 : 0] : states[0]); }
/** * <a href="http://stackoverflow.com/questions/42819618/itext-fill-checkbox-with-value"> * itext fill checkbox with value * </a> * <br/> * <a href="https://www.poreskaupravars.org/Documents/Doc/PD3100.pdf"> * PD3100.pdf * </a> * <p> * This test uses a valid name in append mode and so creates * a PDF displayed in Adobe Reader with a selected field as * desired. * </p> * @see #testPd3100SetVrPr4ToNoAppend() */ @Test public void testPd3100SetVrPr4ToNoAppend() throws IOException, DocumentException { try ( InputStream resource = getClass().getResourceAsStream("PD3100.pdf"); OutputStream result = new FileOutputStream(new File(RESULT_FOLDER, "PD3100-SetVrPr4ToNoAppend.pdf")) ) { PdfReader pdfReader = new PdfReader(resource); PdfStamper pdfStamper = new PdfStamper(pdfReader, result, (char)0, true); AcroFields acroFields = pdfStamper.getAcroFields(); System.out.println("Available values for VrPr4: " + Arrays.asList(acroFields.getAppearanceStates("VrPr4"))); acroFields.setField("VrPr4", "No"); pdfStamper.close(); } }