Chapter 12: Protecting your PDF

These examples were written in the context of Chapter 12 of the book "iText in Action - Second Edition".

Files: 
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part3.chapter12;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
 
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
 
public class MetadataPdf {
    /** The resulting PDF file. */
    public static final String RESULT1
        = "results/part3/chapter12/pdf_metadata.pdf";
    /** The resulting PDF file. */
    public static final String RESULT2
        = "results/part3/chapter12/pdf_metadata_changed.pdf";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException 
     */
    public void createPdf(String filename) throws IOException, DocumentException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.addTitle("Hello World example");
        document.addAuthor("Bruno Lowagie");
        document.addSubject("This example shows how to add metadata");
        document.addKeywords("Metadata, iText, PDF");
        document.addCreator("My program using iText");
        document.open();
        // step 4
        document.add(new Paragraph("Hello World"));
        // step 5
        document.close();
    }
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        Map<String, String> info = reader.getInfo();
        info.put("Title", "Hello World stamped");
        info.put("Subject", "Hello World with changed metadata");
        info.put("Keywords", "iText in Action, PdfStamper");
        info.put("Creator", "Silly standalone example");
        info.put("Author", "Also Bruno Lowagie");
        stamper.setMoreInfo(info);
        stamper.close();
        reader.close();
    }
 
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        MetadataPdf metadata = new MetadataPdf();
        metadata.createPdf(RESULT1);
        metadata.manipulatePdf(RESULT1, RESULT2);
    }
}
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part3.chapter12;
 
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
 
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.xml.xmp.DublinCoreSchema;
import com.itextpdf.text.xml.xmp.PdfSchema;
import com.itextpdf.text.xml.xmp.XmpArray;
import com.itextpdf.text.xml.xmp.XmpSchema;
import com.itextpdf.text.xml.xmp.XmpWriter;
 
public class MetadataXmp {
 
    /** The resulting PDF file. */
    public static final String RESULT1
        = "results/part3/chapter12/xmp_metadata.pdf";
    /** The resulting PDF file. */
    public static final String RESULT2
        = "results/part3/chapter12/xmp_metadata_automatic.pdf";
    /** The resulting PDF file. */
    public static final String RESULT3
        = "results/part3/chapter12/xmp_metadata_added.pdf";
    /** An XML file containing an XMP stream. */
    public static final String RESULT4
        = "results/part3/chapter12/xmp.xml";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException 
     */
    public void createPdf(String filename) throws IOException, DocumentException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT1));
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        XmpWriter xmp = new XmpWriter(os);
        XmpSchema dc = new com.itextpdf.text.xml.xmp.DublinCoreSchema();
        XmpArray subject = new XmpArray(XmpArray.UNORDERED);
        subject.add("Hello World");
        subject.add("XMP & Metadata");
        subject.add("Metadata");
        dc.setProperty(DublinCoreSchema.SUBJECT, subject);
        xmp.addRdfDescription(dc);
        PdfSchema pdf = new PdfSchema();
        pdf.setProperty(PdfSchema.KEYWORDS, "Hello World, XMP, Metadata");
        pdf.setProperty(PdfSchema.VERSION, "1.4");
        xmp.addRdfDescription(pdf);
        xmp.close();
        writer.setXmpMetadata(os.toByteArray());
        // step 3
        document.open();
        // step 4
        document.add(new Paragraph("Hello World"));
        // step 5
        document.close();
    }
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException 
     */
    public void createPdfAutomatic(String filename) throws IOException, DocumentException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        document.addTitle("Hello World example");
        document.addSubject("This example shows how to add metadata & XMP");
        document.addKeywords("Metadata, iText, step 3");
        document.addCreator("My program using 'iText'");
        document.addAuthor("Bruno Lowagie & Paulo Soares");
        writer.createXmpMetadata();
        // step 3
        document.open();
        // step 4
        document.add(new Paragraph("Hello World"));
        // step 5
        document.close();
    }
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        HashMap<String, String> info = reader.getInfo();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        XmpWriter xmp = new XmpWriter(baos, info);
        xmp.close();
        stamper.setXmpMetadata(baos.toByteArray());
        stamper.close();
        reader.close();
    }
 
    /**
     * Reads the XML stream inside a PDF file into an XML file.
     * @param src  A PDF file containing XMP data
     * @param dest XML file containing the XMP data extracted from the PDF
     * @throws IOException
     */
    public void readXmpMetadata(String src, String dest) throws IOException {
        PdfReader reader = new PdfReader(src);
        FileOutputStream fos = new FileOutputStream(dest);
        byte[] b = reader.getMetadata();
        fos.write(b, 0, b.length);
        fos.flush();
        fos.close();
        reader.close();
    }
 
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        MetadataXmp metadata = new MetadataXmp();
        metadata.createPdf(RESULT1);
        metadata.createPdfAutomatic(RESULT2);
        new MetadataPdf().createPdf(MetadataPdf.RESULT1);
        metadata.manipulatePdf(MetadataPdf.RESULT1, RESULT3);
        metadata.readXmpMetadata(RESULT3, RESULT4);
    }
}
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part3.chapter12;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.List;
import com.itextpdf.text.ListItem;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Director;
import com.lowagie.filmfestival.FilmFonts;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;
 
public class HelloWorldCompression {
    /** The resulting PDF file. */
    public static final String RESULT1
        = "results/part3/chapter12/compression_not_at_all.pdf";
    /** The resulting PDF file. */
    public static final String RESULT2
        = "results/part3/chapter12/compression_zero.pdf";
    /** The resulting PDF file. */
    public static final String RESULT3
        = "results/part3/chapter12/compression_normal.pdf";
    /** The resulting PDF file. */
    public static final String RESULT4
        = "results/part3/chapter12/compression_high.pdf";
    /** The resulting PDF file. */
    public static final String RESULT5
        = "results/part3/chapter12/compression_full.pdf";
    /** The resulting PDF file. */
    public static final String RESULT6
        = "results/part3/chapter12/compression_full_too.pdf";
    /** The resulting PDF file. */
    public static final String RESULT7
        = "results/part3/chapter12/compression_removed.pdf";
 
    /**
     * Creates a PDF with information about the movies
     * @param    filename the name of the PDF file that will be created.
     * @throws    DocumentException 
     * @throws    IOException 
     * @throws    SQLException
     */
    public void createPdf(String filename, int compression)
        throws IOException, DocumentException, SQLException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        switch(compression) {
        case -1:
            Document.compress = false;
            break;
        case 0:
            writer.setCompressionLevel(0);
            break;
        case 2:
            writer.setCompressionLevel(9);
            break;
        case 3:
            writer.setFullCompression();
            break;
        }
        // step 3
        document.open();
        // step 4
        // Create database connection and statement
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        Statement stm = connection.createStatement();
        ResultSet rs = stm.executeQuery(
            "SELECT DISTINCT mc.country_id, c.country, count(*) AS c "
            + "FROM film_country c, film_movie_country mc "
            + "WHERE c.id = mc.country_id "
            + "GROUP BY mc.country_id, country ORDER BY c DESC");
        // Create a new list
        List list = new List(List.ORDERED);
        // loop over the countries
        while (rs.next()) {
            // create a list item for the country
            ListItem item = new ListItem(
                String.format("%s: %d movies",
                    rs.getString("country"), rs.getInt("c")),
                FilmFonts.BOLDITALIC);
            // create a movie list for each country
            List movielist = new List(List.ORDERED, List.ALPHABETICAL);
            movielist.setLowercase(List.LOWERCASE);
            for(Movie movie :
                PojoFactory.getMovies(connection, rs.getString("country_id"))) {
                ListItem movieitem = new ListItem(movie.getMovieTitle());
                List directorlist = new List(List.UNORDERED);
                for (Director director : movie.getDirectors()) {
                    directorlist.add(
                        String.format("%s, %s",
                            director.getName(), director.getGivenName()));
                }
                movieitem.add(directorlist);
                movielist.add(movieitem);
            }
            item.add(movielist);
            list.add(item);
        }
        document.add(list);
        // close the statement and the database connection
        stm.close();
        connection.close();
        // step 4
        document.close();
        Document.compress = true;
    }
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @param pow the PDF will be N-upped with N = Math.pow(2, pow);
     * @throws IOException
     * @throws DocumentException
     */
    public void compressPdf(String src, String dest) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest), PdfWriter.VERSION_1_5);
        stamper.getWriter().setCompressionLevel(9);
        int total = reader.getNumberOfPages() + 1;
        for (int i = 1; i < total; i++) {
            reader.setPageContent(i, reader.getPageContent(i));
        }
        stamper.setFullCompression();
        stamper.close();
        reader.close();
    }
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @param pow the PDF will be N-upped with N = Math.pow(2, pow);
     * @throws IOException
     * @throws DocumentException
     */
    public void decompressPdf(String src, String dest) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        Document.compress = false;
        int total = reader.getNumberOfPages() + 1;
        for (int i = 1; i < total; i++) {
            reader.setPageContent(i, reader.getPageContent(i));
        }
        stamper.close();
        reader.close();
        Document.compress = true;
    }
 
    /**
     * Generates a PDF file, then reads it to generate a copy that is fully
     * compressed and one that isn't compressed.
     * 
     * @param args
     *            no arguments needed here
     * @throws SQLException 
     * @throws DocumentException 
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException, DocumentException, SQLException {
        HelloWorldCompression hello = new HelloWorldCompression();
        hello.createPdf(RESULT1, -1);
        hello.createPdf(RESULT2, 0);
        hello.createPdf(RESULT3, 1);
        hello.createPdf(RESULT4, 2);
        hello.createPdf(RESULT5, 3);
        hello.compressPdf(RESULT2, RESULT6);
        hello.decompressPdf(RESULT6, RESULT7);
    }
}
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part3.chapter12;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
 
public class EncryptionPdf {
    /** User password. */
    public static byte[] USER = "Hello".getBytes();
    /** Owner password. */
    public static byte[] OWNER = "World".getBytes();
 
    /** The resulting PDF file. */
    public static final String RESULT1
        = "results/part3/chapter12/encryption.pdf";
    /** The resulting PDF file. */
    public static final String RESULT2
        = "results/part3/chapter12/encryption_decrypted.pdf";
    /** The resulting PDF file. */
    public static final String RESULT3
        = "results/part3/chapter12/encryption_encrypted.pdf";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException 
     */
    public void createPdf(String filename) throws IOException, DocumentException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        writer.setEncryption(USER, OWNER, PdfWriter.ALLOW_PRINTING, PdfWriter.STANDARD_ENCRYPTION_128);
        writer.createXmpMetadata();
        // step 3
        document.open();
        // step 4
        document.add(new Paragraph("Hello World"));
        // step 5
        document.close();
    }
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void decryptPdf(String src, String dest) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(src, OWNER);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        stamper.close();
        reader.close();
    }
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void encryptPdf(String src, String dest) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        stamper.setEncryption(USER, OWNER,
            PdfWriter.ALLOW_PRINTING, PdfWriter.ENCRYPTION_AES_128 | PdfWriter.DO_NOT_ENCRYPT_METADATA);
        stamper.close();
        reader.close();
    }
 
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        EncryptionPdf metadata = new EncryptionPdf();
        metadata.createPdf(RESULT1);
        metadata.decryptPdf(RESULT1, RESULT2);
        metadata.encryptPdf(RESULT2, RESULT3);
    }
}
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part3.chapter12;
 
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Properties;
 
import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
 
public class EncryptWithCertificate {
 
    /** The resulting PDF */
    public static String RESULT1 = "results/part3/chapter12/certificate_encryption.pdf";
    /** The resulting PDF */
    public static String RESULT2 = "results/part3/chapter12/certificate_decrypted.pdf";
    /** The resulting PDF */
    public static String RESULT3 = "results/part3/chapter12/certificate_encrypted.pdf";
 
    /**
     * A properties file that is PRIVATE.
     * You should make your own properties file and adapt this line.
     */
    public static String PATH = "c:/home/blowagie/key.properties";
    /** Some properties used when signing. */
    public static Properties properties = new Properties();
 
    /**
     * Creates a PDF that is encrypted using two different public certificates.
     * @param filename the path to the resulting PDF file
     * @throws IOException
     * @throws DocumentException
     * @throws GeneralSecurityException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, GeneralSecurityException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT1));
        Certificate cert1 = getPublicCertificate("resources/encryption/foobar.cer");
        Certificate cert2 = getPublicCertificate(properties.getProperty("PUBLIC"));
        writer.setEncryption(new Certificate[]{cert1, cert2},
            new int[]{PdfWriter.ALLOW_PRINTING, PdfWriter.ALLOW_COPY}, PdfWriter.ENCRYPTION_AES_128);
        // step 3
        document.open();
        // step 4
        document.add(new Paragraph("Hello World!"));
        // step 5
        document.close();
    }
 
    /**
     * Gets a public certificate from a certificate file.
     * @param path the path to the certificate
     * @return a Certificate object
     * @throws IOException
     * @throws CertificateException
     */
    public Certificate getPublicCertificate(String path)
        throws IOException, CertificateException {
        FileInputStream is = new FileInputStream(path);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
        return cert;
    }
 
    /**
     * Gets a private key from a KeyStore.
     * @return a PrivateKey object
     * @throws GeneralSecurityException
     * @throws IOException
     */
    public PrivateKey getPrivateKey() throws GeneralSecurityException, IOException {
        String path = "resources/encryption/.keystore";
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(new FileInputStream(path), "f00b4r".toCharArray());
        PrivateKey pk = (PrivateKey)ks.getKey("foobar", "f1lmf3st".toCharArray());
        return pk;
    }
 
    /**
     * Decrypts a PDF that was encrypted using a certificate
     * @param src  The encrypted PDF
     * @param dest The decrypted PDF
     * @throws IOException
     * @throws DocumentException
     * @throws GeneralSecurityException
     */
    public void decryptPdf(String src, String dest)
        throws IOException, DocumentException, GeneralSecurityException {
        PdfReader reader = new PdfReader(src,
            getPublicCertificate("resources/encryption/foobar.cer"), getPrivateKey(), "BC");
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        stamper.close();
        reader.close();
    }
 
    /**
     * Encrypts a PDF using a public certificate.
     * @param src  The original PDF document
     * @param dest The encrypted PDF document
     * @throws IOException
     * @throws DocumentException
     * @throws CertificateException
     */
    public void encryptPdf(String src, String dest)
        throws IOException, DocumentException, CertificateException {
        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        Certificate cert = getPublicCertificate("resources/encryption/foobar.cer");
        stamper.setEncryption(new Certificate[]{cert},
            new int[]{PdfWriter.ALLOW_PRINTING}, PdfWriter.ENCRYPTION_AES_128);
        stamper.close();
        reader.close();
    }
 
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws GeneralSecurityException 
     */
    public static void main(String[] args)
        throws IOException, DocumentException, GeneralSecurityException {
        Security.addProvider(new BouncyCastleProvider());
        properties.load(new FileInputStream(PATH));
        EncryptWithCertificate hello = new EncryptWithCertificate();
        hello.createPdf(RESULT1);
        hello.decryptPdf(RESULT1, RESULT2);
        hello.encryptPdf(RESULT2, RESULT3);
    }
}
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
 
package part3.chapter12;
 
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.util.Properties;
 
import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfAppearance;
import com.itextpdf.text.pdf.PdfFormField;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature.MakeSignature.CryptoStandard" target="_blank" style="color: #cc6600;">CryptoStandard;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
import com.itextpdf.text.pdf.security.MakeSignature;
 
public class SignatureField {
 
    /** The resulting PDF */
    public static String ORIGINAL = "results/part3/chapter12/unsigned.pdf";
    /** The resulting PDF */
    public static String SIGNED1 = "results/part3/chapter12/signed_1.pdf";
    /** The resulting PDF */
    public static String SIGNED2 = "results/part3/chapter12/signed_2.pdf";
 
    /** One of the resources. */
    public static final String RESOURCE
        = "resources/img/1t3xt.gif";
 
    /**
     * A properties file that is PRIVATE.
     * You should make your own properties file and adapt this line.
     */
    public static String PATH = "c:/home/blowagie/key.properties";
    /** Some properties used when signing. */
    public static Properties properties = new Properties();
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException 
     */
    public void createPdf(String filename) throws IOException, DocumentException {
    	// step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        document.add(new Paragraph("Hello World!"));
        PdfFormField field = PdfFormField.createSignature(writer);
        field.setWidget(new Rectangle(72, 732, 144, 780), PdfAnnotation.HIGHLIGHT_INVERT);
        field.setFieldName("mySig");
        field.setFlags(PdfAnnotation.FLAGS_PRINT);
        field.setPage();
        field.setMKBorderColor(BaseColor.BLACK);
        field.setMKBackgroundColor(BaseColor.WHITE);
        PdfAppearance tp = PdfAppearance.createAppearance(writer, 72, 48);
        tp.rectangle(0.5f, 0.5f, 71.5f, 47.5f);
        tp.stroke();
        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
        writer.addAnnotation(field);
        // step 5
        document.close();
    }
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws GeneralSecurityException 
     * @throws IOException 
     * @throws DocumentException 
     * @throws FileNotFoundException 
     * @throws KeyStoreException 
     * @throws Exception 
     */
    public void signPdf(String src, String dest, boolean certified, boolean graphic) throws GeneralSecurityException, IOException, DocumentException {
        // private key and certificate
    	String path = properties.getProperty("PRIVATE");
        String keystore_password = properties.getProperty("PASSWORD");
        String key_password = properties.getProperty("PASSWORD");
        KeyStore ks = KeyStore.getInstance("pkcs12", "BC");
        ks.load(new FileInputStream(path), keystore_password.toCharArray());
        String alias = (String)ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey)ks.getKey(alias, key_password.toCharArray());
        Certificate[] chain = ks.getCertificateChain(alias);
        // reader and stamper
        PdfReader reader = new PdfReader(ORIGINAL);
        PdfStamper stamper = PdfStamper.createSignature(reader, new FileOutputStream(dest), '\0');
        // appearance
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setVisibleSignature("mySig");
        appearance.setReason("It's personal.");
        appearance.setLocation("Foobar");
        if (certified)
            appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);
        if (graphic) {
            appearance.setSignatureGraphic(Image.getInstance(RESOURCE));
            appearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);
        }
        // signature
        ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
        ExternalDigest digest = new BouncyCastleDigest();
        MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, MakeSignature.CryptoStandard" target="_blank" style="color: #cc6600;">CryptoStandard.CMS);
    }
 
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     */
    public static void main(String[] args)
        throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        properties.load(new FileInputStream(PATH));
        SignatureField signatures = new SignatureField();
        signatures.createPdf(ORIGINAL);
        signatures.signPdf(ORIGINAL, SIGNED1, false, false);
        signatures.signPdf(ORIGINAL, SIGNED2, true, true);
    }
}
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part3.chapter12;
 
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Properties;
 
import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.CertificateInfo;
import com.itextpdf.text.pdf.security.CertificateVerification;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature.MakeSignature.CryptoStandard" target="_blank" style="color: #cc6600;">CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.PdfPKCS7;
import com.itextpdf.text.pdf.security.VerificationException;
 
public class Signatures {
 
    /** The resulting PDF */
    public static String ORIGINAL = "results/part3/chapter12/hello.pdf";
    /** The resulting PDF */
    public static String SIGNED1 = "results/part3/chapter12/signature_1.pdf";
    /** The resulting PDF */
    public static String SIGNED2 = "results/part3/chapter12/signature_2.pdf";
    /** Info after verification of a signed PDF */
    public static String VERIFICATION = "results/part3/chapter12/verify.txt";
    /** The resulting PDF */
    public static String REVISION = "results/part3/chapter12/revision_1.pdf";
 
    /**
     * A properties file that is PRIVATE.
     * You should make your own properties file and adapt this line.
     */
    public static String PATH = "c:/home/blowagie/key.properties";
    /** Some properties used when signing. */
    public static Properties properties = new Properties();
    /** One of the resources. */
    public static final String RESOURCE = "resources/img/logo.gif";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException 
     */
    public void createPdf(String filename) throws IOException, DocumentException {
        Document document = new Document();
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        document.open();
        document.add(new Paragraph("Hello World!"));
        document.close();
    }
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     * @throws GeneralSecurityException 
     */
    public void signPdfFirstTime(String src, String dest)
        throws IOException, DocumentException, GeneralSecurityException {
        String path = properties.getProperty("PRIVATE");
        String keystore_password = properties.getProperty("PASSWORD");
        String key_password = properties.getProperty("PASSWORD");
        KeyStore ks = KeyStore.getInstance("pkcs12", "BC");
        ks.load(new FileInputStream(path), keystore_password.toCharArray());
        String alias = (String)ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey) ks.getKey(alias, key_password.toCharArray());
        Certificate[] chain = ks.getCertificateChain(alias);
        // reader and stamper
        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
        // appearance
        PdfSignatureAppearance appearance = stamper .getSignatureAppearance();
        appearance.setImage(Image.getInstance(RESOURCE));
        appearance.setReason("I've written this.");
        appearance.setLocation("Foobar");
        appearance.setVisibleSignature(new Rectangle(72, 732, 144, 780), 1,    "first");
        // digital signature
        ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
        ExternalDigest digest = new BouncyCastleDigest();
        MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, MakeSignature.CryptoStandard" target="_blank" style="color: #cc6600;">CryptoStandard.CMS);
    }
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     * @throws GeneralSecurityException 
     */
    public void signPdfSecondTime(String src, String dest)
        throws IOException, DocumentException, GeneralSecurityException {
        String path = "resources/encryption/.keystore";
        String keystore_password = "f00b4r";
        String key_password = "f1lmf3st";
        String alias = "foobar";
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(new FileInputStream(path), keystore_password.toCharArray());
        PrivateKey pk = (PrivateKey) ks.getKey(alias, key_password.toCharArray());
        Certificate[] chain = ks.getCertificateChain(alias);
        // reader / stamper
        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
        // appearance
        PdfSignatureAppearance appearance = stamper
                .getSignatureAppearance();
        appearance.setReason("I'm approving this.");
        appearance.setLocation("Foobar");
        appearance.setVisibleSignature(new Rectangle(160, 732, 232, 780), 1, "second");
        // digital signature
        ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
        ExternalDigest digest = new BouncyCastleDigest();
        MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, MakeSignature.CryptoStandard" target="_blank" style="color: #cc6600;">CryptoStandard.CMS);
 
    }
 
    /**
     * Verifies the signatures of a PDF we've signed twice.
     * @throws GeneralSecurityException
     * @throws IOException
     */
    public void verifySignatures() throws GeneralSecurityException, IOException {
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(null, null);
        CertificateFactory cf = CertificateFactory.getInstance("X509");
        FileInputStream is1 = new FileInputStream(properties.getProperty("ROOTCERT"));
        X509Certificate cert1 = (X509Certificate) cf.generateCertificate(is1);
        ks.setCertificateEntry("cacert", cert1);
        FileInputStream is2 = new FileInputStream("resources/encryption/foobar.cer");
        X509Certificate cert2 = (X509Certificate) cf.generateCertificate(is2);
        ks.setCertificateEntry("foobar", cert2);
 
        PrintWriter out = new PrintWriter(new FileOutputStream(VERIFICATION));
        PdfReader reader = new PdfReader(SIGNED2);
        AcroFields af = reader.getAcroFields();
        ArrayList<String> names = af.getSignatureNames();
        for (String name : names) {
            out.println("Signature name: " + name);
            out.println("Signature covers whole document: " + af.signatureCoversWholeDocument(name));
            out.println("Document revision: " + af.getRevision(name) + " of " + af.getTotalRevisions());
            PdfPKCS7 pk = af.verifySignature(name);
            Calendar cal = pk.getSignDate();
            Certificate[] pkc = pk.getCertificates();
            out.println("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate()));
            out.println("Revision modified: " + !pk.verify());
            List<VerificationException> errors = CertificateVerification.verifyCertificates(pkc, ks, null, cal);
            if (errors.size() == 0)
                out.println("Certificates verified against the KeyStore");
            else
                out.println(errors);    
        }
        out.flush();
        out.close();
    }
 
    /**
     * Extracts the first revision of a PDF we've signed twice.
     * @throws IOException
     */
    public void extractFirstRevision() throws IOException {
        PdfReader reader = new PdfReader(SIGNED2);
        AcroFields af = reader.getAcroFields();
        FileOutputStream os = new FileOutputStream(REVISION);
        byte bb[] = new byte[1028];
        InputStream ip = af.extractRevision("first");
        int n = 0;
        while ((n = ip.read(bb)) > 0)
            os.write(bb, 0, n);
        os.close();
        ip.close();
    }
 
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws GeneralSecurityException 
     */
    public static void main(String[] args)
        throws IOException, DocumentException, GeneralSecurityException {
        Security.addProvider(new BouncyCastleProvider());
        properties.load(new FileInputStream(PATH));
        Signatures signatures = new Signatures();
        signatures.createPdf(ORIGINAL);
        signatures.signPdfFirstTime(ORIGINAL, SIGNED1);
        signatures.signPdfSecondTime(SIGNED1, SIGNED2);
        signatures.verifySignatures();
        signatures.extractFirstRevision();
    }
}
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part3.chapter12;
 
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.util.Properties;
 
import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature.MakeSignature.CryptoStandard" target="_blank" style="color: #cc6600;">CryptoStandard;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
import com.itextpdf.text.pdf.security.MakeSignature;
 
public class SignatureExternalHash {
 
    /**
     * A properties file that is PRIVATE.
     * You should make your own properties file and adapt this line.
     */
    public static String PATH = "c:/home/blowagie/key.properties";
    /** Some properties used when signing. */
    public static Properties properties = new Properties();
 
    /** The resulting PDF */
    public static String SIGNED1 = "results/part3/chapter12/externalhash_1.pdf";
    /** The resulting PDF */
    public static String SIGNED2 = "results/part3/chapter12/externalhash_2.pdf";
    /** The resulting PDF */
    public static String SIGNED3 = "results/part3/chapter12/externalhash_3.pdf";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws GeneralSecurityException 
     * @throws IOException 
     * @throws DocumentException 
     * @throws FileNotFoundException 
     * @throws KeyStoreException 
     * @throws Exception 
     */
    public void signPdfDetached(String src, String dest) throws GeneralSecurityException, IOException, DocumentException {
    	// Private key and certificate
        String path = properties.getProperty("PRIVATE");
        String keystore_password = properties.getProperty("PASSWORD");
        String key_password = properties.getProperty("PASSWORD");
        KeyStore ks = KeyStore.getInstance("pkcs12", "BC");
        ks.load(new FileInputStream(path), keystore_password.toCharArray());
        String alias = (String)ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey) ks.getKey(alias, key_password.toCharArray());
        Certificate[] chain = ks.getCertificateChain(alias);
 
        // reader and stamper
        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
 
        // appearance
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setReason("External hash example");
        appearance.setLocation("Foobar");
        appearance.setVisibleSignature(new Rectangle(72, 732, 144, 780), 1, "sig");
 
        // digital signature
        ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
        ExternalDigest digest = new BouncyCastleDigest();
        MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, MakeSignature.CryptoStandard" target="_blank" style="color: #cc6600;">CryptoStandard.CMS);
    }
 
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws GeneralSecurityException 
     */
    public static void main(String[] args)
        throws IOException, DocumentException, GeneralSecurityException {
        Security.addProvider(new BouncyCastleProvider());
        properties.load(new FileInputStream(PATH));
        new Signatures().createPdf(Signatures.ORIGINAL);
        SignatureExternalHash signatures = new SignatureExternalHash();
        signatures.signPdfDetached(Signatures.ORIGINAL, SIGNED1);
    }
}
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part3.chapter12;
 
public class SignWithBC {
 
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     */
    public static void main(String[] args) {
    	System.out.println("This example is no longer relevant.");
    }
}
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part3.chapter12;
 
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.util.Properties;
 
import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature.MakeSignature.CryptoStandard" target="_blank" style="color: #cc6600;">CryptoStandard;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.OcspClient;
import com.itextpdf.text.pdf.security.OcspClientBouncyCastle;
import com.itextpdf.text.pdf.security.TSAClient;
import com.itextpdf.text.pdf.security.TSAClientBouncyCastle;
 
public class TimestampOCSP {
 
    /** The resulting PDF */
    public static String SIGNED0 = "results/part3/chapter12/without.pdf";
    /** The resulting PDF */
    public static String SIGNED1 = "results/part3/chapter12/ts.pdf";
    /** The resulting PDF */
    public static String SIGNED2 = "results/part3/chapter12/ocsp.pdf";
    /** The resulting PDF */
    public static String SIGNED3 = "results/part3/chapter12/ts_oscp.pdf";
 
    /**
     * A properties file that is PRIVATE.
     * You should make your own properties file and adapt this line.
     */
    public static String PATH = "c:/home/blowagie/key.properties";
    /** Some properties used when signing. */
    public static Properties properties = new Properties();
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     * @throws GeneralSecurityException 
     */
    public void signPdf(String src, String dest, boolean withTS, boolean withOCSP)
        throws IOException, DocumentException, GeneralSecurityException {
        // Keystore and certificate chain
    	String keystore = properties.getProperty("PRIVATE");
        String password = properties.getProperty("PASSWORD");
        KeyStore ks = KeyStore.getInstance("PKCS12", "BC");
        ks.load(new FileInputStream(keystore), password.toCharArray());
        String alias = (String)ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey)ks.getKey(alias, password.toCharArray());
        Certificate[] chain = ks.getCertificateChain(alias);
        // reader and stamper
        PdfReader reader = new PdfReader(src);
        FileOutputStream fout = new FileOutputStream(dest);
        PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');
        // appearance
        PdfSignatureAppearance sap = stp.getSignatureAppearance();
        sap.setReason("I'm approving this.");
        sap.setLocation("Foobar");
        sap.setVisibleSignature(new Rectangle(72, 732, 144, 780), 1, "Signature");
        // preserve some space for the contents
        // digital signature
        ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
        // If we add a time stamp:
        TSAClient tsc = null;
        if (withTS) {
            String tsa_url    = properties.getProperty("TSA");
            String tsa_login  = properties.getProperty("TSA_LOGIN");
            String tsa_passw  = properties.getProperty("TSA_PASSWORD");
            tsc = new TSAClientBouncyCastle(tsa_url, tsa_login, tsa_passw);
        }
        // If we use OCSP:
        OcspClient ocsp = null;
        if (withOCSP) {
            ocsp = new OcspClientBouncyCastle();
        }
        ExternalDigest digest = new BouncyCastleDigest();
        MakeSignature.signDetached(sap, digest, es, chain, null, ocsp, tsc, 0, MakeSignature.CryptoStandard" target="_blank" style="color: #cc6600;">CryptoStandard.CMS);
    }
 
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws GeneralSecurityException 
     */
    public static void main(String[] args)
        throws IOException, DocumentException, GeneralSecurityException {
        Security.addProvider(new BouncyCastleProvider());
        properties.load(new FileInputStream(PATH));
        new Signatures().createPdf(Signatures.ORIGINAL);
        TimestampOCSP signatures = new TimestampOCSP();
        signatures.signPdf(Signatures.ORIGINAL, SIGNED0, false, false);
        signatures.signPdf(Signatures.ORIGINAL, SIGNED1, true, false);
        signatures.signPdf(Signatures.ORIGINAL, SIGNED2, false, true);
        signatures.signPdf(Signatures.ORIGINAL, SIGNED3, true, true);
    }
}
File nameRaw URLUpdated
MetadataPdf.javaMetadataPdf.java2015-10-10 3:16 pm
MetadataXmp.javaMetadataXmp.java2015-10-10 3:16 pm
HelloWorldCompression.javaHelloWorldCompression.java2015-10-10 3:16 pm
EncryptionPdf.javaEncryptionPdf.java2015-10-10 3:16 pm
EncryptWithCertificate.javaEncryptWithCertificate.java2015-10-10 3:16 pm
SignatureField.javaSignatureField.java2015-10-10 3:16 pm
Signatures.javaSignatures.java2015-10-10 3:16 pm
SignatureExternalHash.javaSignatureExternalHash.java2015-10-10 3:16 pm
SignWithBC.javaSignWithBC.java2015-10-10 3:16 pm
TimestampOCSP.javaTimestampOCSP.java2015-10-10 3:16 pm
C# port: 
File nameRaw URLUpdated
MetadataPdf.csMetadataPdf.cs2015-10-10 3:17 pm
MetadataXmp.csMetadataXmp.cs2015-10-10 3:17 pm
HelloWorldCompression.csHelloWorldCompression.cs2015-10-10 3:17 pm
EncryptionPdf.csEncryptionPdf.cs2015-10-10 3:17 pm