import org.faceless.pdf2.*; import java.security.*; import java.net.*; import java.util.*; import java.io.*; import java.awt.Color; import java.awt.color.*; public class Test { private static final String config = "name=OpenSC\nlibrary=/Library/OpenSC/lib/opensc-pkcs11.so"; // Config for your PKCS#11 driver private static final String pin = "0000"; // Pin for your PKCS#11 card private static final String keystorefile = "keystore.jks"; // Path to regular keystore private static final String alias = "alias"; // Keystore alias private static final String password = "password"; // Keystore password private static final String fonturl = "http://fonts.gstatic.com/s/cardo/v11/wlp_gwjKBV1pqhv43IE7225P.woff2"; // A font private static final String tsaurl = "https://freetsa.org/tsr"; // A timestamp server private static final ICC_Profile icc = ICC_Profile.getInstance(ColorSpace.CS_sRGB); public static void main(String[] args) throws Exception { file1(); file2(); file3(); file4(); file5(); file6(); file7(); file8(); file9(); file10(); file11(); file12(); } public static void file1() throws Exception { // 1. Retrieve some resources PDFFont font = new OpenTypeFont(new URL(fonturl)); OutputProfile profile = new OutputProfile(OutputProfile.PDFA3a, "sRGB", null, "http://www.color.org", null, icc); profile.setDenied(OutputProfile.Feature.RegularCompression); // Don't compress any streams in the file. // 2. Create a simple PDF/A3 PDF PDF pdf = new PDF(profile); PDFPage page = pdf.newPage("A4"); PDFStyle style = new PDFStyle(); style.setFont(font, 24); style.setFillColor(Color.black); LayoutBox box = new LayoutBox(500); box.beginTag("P", Collections.singletonMap("ActualText", "I am here to do good.")); box.addText("I am here to do good.", style, null); box.endTag(); page.drawLayoutBox(box, 50, 800); pdf.setInfo("Title", "A Good Document"); pdf.setInfo("Author", "Alice"); // 3. Sign the PDF with a PAdES LTV signature. Provider provider = new sun.security.pkcs11.SunPKCS11(new ByteArrayInputStream(config.getBytes("ISO-8859-1"))); AcrobatSignatureHandlerFactory factory = new AcrobatSignatureHandlerFactory(); factory.setTimeStampServer(new URL(tsaurl)); factory.setPAdES(true); factory.setValidateCertificatesOnSigning(true); KeyStore keystore = KeyStore.getInstance("pkcs11", provider); keystore.load(null, pin.toCharArray()); FormSignature sig = new FormSignature(); String alias = keystore.aliases().nextElement(); // Because there's probably only one. sig.sign(keystore, alias, pin.toCharArray(), factory); pdf.getForm().getElements().put("Sig1", sig); // 4. Save the PDF OutputStream fo = new FileOutputStream("file1.pdf"); pdf.render(fo); fo.close(); } public static void file2() throws Exception { PDF pdf = new PDF(new PDFReader(new File("file1.pdf"))); pdf.rebuildStructureTree(); pdf.setInfo("Title", "An Evil Document"); pdf.setInfo("Author", "Eve"); pdf.render(new FileOutputStream("file2.pdf")); // PDF must be hand modified to alter the logical structure after saving } public static void file3() throws Exception { // 1. Retrieve some resources ICC_Profile icc = ICC_Profile.getInstance(ColorSpace.CS_sRGB); PDFFont font = new OpenTypeFont(new URL(fonturl)); OutputProfile profile = new OutputProfile(OutputProfile.PDFA3a, "sRGB", null, "http://www.color.org", null, icc); profile.setDenied(OutputProfile.Feature.RegularCompression); // Don't compress any streams in the file. // 2. Create a simple PDF/A3 PDF PDF pdf = new PDF(profile); PDFPage page = pdf.newPage("A4"); PDFStyle style = new PDFStyle(); style.setFont(font, 24); style.setFillColor(Color.black); LayoutBox box = new LayoutBox(500); box.beginTag("P", Collections.singletonMap("ActualText", "I am here to do good.")); box.addText("I am here to do good.", style, null); box.endTag(); page.drawLayoutBox(box, 50, 800); pdf.setInfo("Title", "A Good Document"); pdf.setInfo("Author", "Alice"); // 3. Sign the PDF with an original-style digital signature. AcrobatSignatureHandlerFactory factory = new AcrobatSignatureHandlerFactory(); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(new FileInputStream(keystorefile), password.toCharArray()); FormSignature sig = new FormSignature(); sig.sign(keystore, alias, password.toCharArray(), factory); pdf.getForm().getElements().put("Sig1", sig); // 4. Save the PDF OutputStream fo = new FileOutputStream("file3.pdf"); pdf.render(fo); fo.close(); // Copy file3 to file3b, with an extra space InputStream in = new BufferedInputStream(new FileInputStream("file3.pdf")); int c; fo = new BufferedOutputStream(new FileOutputStream("file3b.pdf")); while ((c=in.read())>=0) { fo.write(c); } fo.write(0x0a); fo.close(); in.close(); } // Regular signature with new page added public static void file4() throws Exception { PDF pdf = new PDF(new PDFReader(new File("file3.pdf"))); pdf.newPage("A4"); pdf.render(new FileOutputStream("file4.pdf")); } // Regular signature with new revision changing only metadata public static void file5() throws Exception { PDF pdf = new PDF(new PDFReader(new File("file3.pdf"))); pdf.render(new FileOutputStream("file5.pdf")); } // Certifying signature, regular keystore // This one didn't make the edit. public static void file6() throws Exception { // 1. Retrieve some resources ICC_Profile icc = ICC_Profile.getInstance(ColorSpace.CS_sRGB); PDFFont font = new OpenTypeFont(new URL(fonturl)); OutputProfile profile = new OutputProfile(OutputProfile.PDFA3a, "sRGB", null, "http://www.color.org", null, icc); profile.setDenied(OutputProfile.Feature.RegularCompression); // Don't compress any streams in the file. // 2. Create a simple PDF/A3 PDF PDF pdf = new PDF(profile); PDFPage page = pdf.newPage("A4"); PDFStyle style = new PDFStyle(); style.setFont(font, 24); style.setFillColor(Color.black); LayoutBox box = new LayoutBox(500); box.beginTag("P", Collections.singletonMap("ActualText", "I am here to do good.")); box.addText("I am here to do good.", style, null); box.endTag(); page.drawLayoutBox(box, 50, 800); pdf.setInfo("Title", "Original Title"); pdf.setInfo("Creator", "Original Creator"); // 3. Sign the PDF with an original-style digital signature. AcrobatSignatureHandlerFactory factory = new AcrobatSignatureHandlerFactory(); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(new FileInputStream(keystorefile), password.toCharArray()); FormSignature sig = new FormSignature(); sig.setCertificationType(FormSignature.CERTIFICATION_NOCHANGES, null); sig.sign(keystore, alias, password.toCharArray(), factory); pdf.getForm().getElements().put("Sig1", sig); // 4. Save the PDF OutputStream fo = new FileOutputStream("file5.pdf"); pdf.render(fo); fo.close(); // Copy file6 to file6b, with an extra space InputStream in = new BufferedInputStream(new FileInputStream("file6.pdf")); int c; fo = new BufferedOutputStream(new FileOutputStream("file6b.pdf")); while ((c=in.read())>=0) { fo.write(c); } fo.write(0x0a); fo.close(); in.close(); } // Certifying signature with a single revision. Also dropped public static void file7() throws Exception { PDF pdf = new PDF(new PDFReader(new File("file6.pdf"))); pdf.render(new FileOutputStream("file7.pdf")); } public static byte[] formCreation(boolean button) throws IOException { PDF pdf = new PDF(); PDFPage page = pdf.newPage("A4"); // Create the page labels - nothing to do with forms, // but included to make the document more complete. PDFStyle label = new PDFStyle(); label.setFillColor(Color.black); label.setFont(new StandardFont(StandardFont.HELVETICA), 11); page.setStyle(label); page.drawText("Name:", 100, 708); page.drawText("Year of birth:", 100, 668); page.drawText("Address:", 330, 708); page.drawText("Rating:", 100, 628); page.drawText("1", 155, 628); page.drawText("5", 255, 628); page.drawText("Yes, send me spam!:", 330, 628); // Now we begin the forms specific bits - we get the form from the // PDF, and set a default style for any new elements that we create. // The background style can have a fill color, line color, line // weighting, line dash pattern and form style set. Form form = pdf.getForm(); PDFStyle background = new PDFStyle(); background.setFillColor(new Color(240, 240, 255)); background.setLineColor(Color.blue); background.setFormStyle(PDFStyle.FORMSTYLE_BEVEL); form.setBackgroundStyle(background); // Create the first field - a text field called "name" FormText name = new FormText(page, 170, 700, 300, 720); form.addElement("Name", name); // Create the second field - a multiline text box for the Address FormText address = new FormText(page, 400, 660, 550, 720); address.setType(FormText.TYPE_MULTILINE); form.addElement("Address", address); // Create the third field - a pull-down menu of months FormChoice month = new FormChoice(FormChoice.TYPE_DROPDOWN, page , 170, 660, 230, 680); month.getOptions().put("Jan", null); month.getOptions().put("Feb", null); month.getOptions().put("Mar", null); month.getOptions().put("Apr", null); month.getOptions().put("May", null); month.getOptions().put("Jun", null); month.getOptions().put("Jul", null); month.getOptions().put("Aug", null); month.getOptions().put("Sep", null); month.getOptions().put("Oct", null); month.getOptions().put("Nov", null); month.getOptions().put("Dec", null); form.addElement("Month", month); // Create the fourth field - a text field containing a year. // Add some JavaScript constraints which limit this field to // numeric values between 1900 and 2000 FormText year = new FormText(page, 240, 660, 300, 680); year.setMaxLength(4); WidgetAnnotation annot = year.getAnnotation(0); year.setAction(Event.KEYPRESS, PDFAction.formJavaScript("AFNumber_Keystroke(0, 1, 1, 0, '', true);")); year.setAction(Event.CHANGE, PDFAction.formJavaScript("AFRange_Validate(true, 1900, true, 2000);")); form.addElement("Year", year); // Create a set of five radio buttons, the fifth field. if (button) { FormRadioButton rating = new FormRadioButton(); rating.addAnnotation("1", page, 170, 627, 180, 637); form.addElement("Rating", rating); } ByteArrayOutputStream out = new ByteArrayOutputStream(); pdf.render(out); out.close(); return out.toByteArray(); } // Form fields (ok) public static void file8() throws Exception { PDF pdf = new PDF(new PDFReader(new ByteArrayInputStream(formCreation(false)))); AcrobatSignatureHandlerFactory factory = new AcrobatSignatureHandlerFactory(); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(new FileInputStream(keystorefile), password.toCharArray()); FormSignature sig = new FormSignature(); sig.sign(keystore, alias, password.toCharArray(), factory); pdf.getForm().getElements().put("Sig1", sig); OutputStream fo = new FileOutputStream("file8.pdf"); pdf.render(fo); fo.close(); } // Form fields (ok) - counter-signed. public static void file9() throws Exception { PDF pdf = new PDF(new PDFReader(new FileInputStream("file8.pdf"))); AcrobatSignatureHandlerFactory factory = new AcrobatSignatureHandlerFactory(); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(new FileInputStream(keystorefile), password.toCharArray()); FormSignature sig = new FormSignature(); sig.sign(keystore, alias, password.toCharArray(), factory); pdf.getForm().getElements().put("Sig2", sig); OutputStream fo = new FileOutputStream("file9.pdf"); pdf.render(fo); fo.close(); } // Form fields (bad) public static void file10() throws Exception { PDF pdf = new PDF(new PDFReader(new ByteArrayInputStream(formCreation(true)))); AcrobatSignatureHandlerFactory factory = new AcrobatSignatureHandlerFactory(); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(new FileInputStream(keystorefile), password.toCharArray()); FormSignature sig = new FormSignature(); sig.sign(keystore, alias, password.toCharArray(), factory); pdf.getForm().getElements().put("Sig1", sig); OutputStream fo = new FileOutputStream("file10.pdf"); pdf.render(fo); fo.close(); } // Form fields (bad) - counter-signed public static void file11() throws Exception { PDF pdf = new PDF(new PDFReader(new FileInputStream("file10.pdf"))); AcrobatSignatureHandlerFactory factory = new AcrobatSignatureHandlerFactory(); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(new FileInputStream(keystorefile), password.toCharArray()); FormSignature sig = new FormSignature(); sig.sign(keystore, alias, password.toCharArray(), factory); pdf.getForm().getElements().put("Sig2", sig); OutputStream fo = new FileOutputStream("file11.pdf"); pdf.render(fo); fo.close(); } // Form fields (bad) - modified public static void file12() throws Exception { PDF pdf = new PDF(new PDFReader(new File("file10.pdf"))); pdf.render(new FileOutputStream("file12.pdf")); } }