Chapter 12: Protecting your PDF

This is a code example of iText PDF, discover more.

10th October 2015
admin-marketing

Switch code for this example

MetadataPdf.java
/*
 * 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 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);
    }
}
MetadataXmp.java
/*
 * 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 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);
    }
}
HelloWorldCompression.java
/*
 * 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);
    }
}
EncryptionPdf.java
/*
 * 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);
    }
}
EncryptWithCertificate.java
/*
 * 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);
    }
}
SignatureField.java
/*
 * 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.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, 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);
    }
}
Signatures.java
/*
 * 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.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, 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, 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 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 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();
    }
}
SignatureExternalHash.java
/*
 * 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.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, 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);
    }
}
SignWithBC.java
/*
 * 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.");
    }
}
TimestampOCSP.java
/*
 * 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.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, 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);
    }
}
MetadataPdf.cs
/*
 * 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.
 */
using System;
using System.IO;
using System.Collections.Generic;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter12 {
  public class MetadataPdf : IWriter {
// ===========================================================================
    /** The resulting PDF file. */
    public const string RESULT1 = "pdf_metadata.pdf";
    /** The resulting PDF file. */
    public const string RESULT2 = "pdf_metadata_changed.pdf";
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MetadataPdf metadata = new MetadataPdf();
        byte[] pdf = metadata.CreatePdf();
        zip.AddEntry(RESULT1, pdf);
        zip.AddEntry(RESULT2, metadata.ManipulatePdf(pdf));
        zip.Save(stream);
      }
    }
// ---------------------------------------------------------------------------
/**
 * Creates a PDF document.
 */
    public byte[] CreatePdf() {
      using (MemoryStream ms = new MemoryStream()) {
        // step 1
        using (Document document = new Document()) {
          // step 2
          PdfWriter.GetInstance(document, ms);
          // 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"));
        }
        return ms.ToArray();    
      }
    }    
// ---------------------------------------------------------------------------
/**
 * Manipulates a PDF file src with the file dest as result
 * @param src the original PDF
 */
    public byte[] ManipulatePdf(byte[] src) {
      PdfReader reader = new PdfReader(src);
      using (MemoryStream ms = new MemoryStream()) {
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          Dictionary info = reader.Info;
          info["Title"] = "Hello World stamped";
          info["Subject"] = "Hello World with changed metadata";
          info["Keywords"] = "iText in Action, PdfStamper";
          info["Creator"] = "Silly standalone example";
          info["Author"] = "Also Bruno Lowagie";
          stamper.MoreInfo = info;
        }
        return ms.ToArray();
      }
    }  
// ===========================================================================
  }
}
MetadataXmp.cs
/*
 * 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.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.xml.xmp;

namespace kuujinbo.iTextInAction2Ed.Chapter12 {
  public class MetadataXmp : IWriter {
// ===========================================================================
    /** The resulting PDF file. */
    public const string RESULT1 = "xmp_metadata.pdf";
    /** The resulting PDF file. */
    public const string RESULT2 = "xmp_metadata_automatic.pdf";
    /** The resulting PDF file. */
    public const string RESULT3 = "xmp_metadata_added.pdf";
    /** The resulting PDF file. */
    public const string RESULT4 = "xmp.xml";
// ---------------------------------------------------------------------------        
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MetadataXmp metadata = new MetadataXmp();
        byte[] pdf = metadata.CreatePdf();
        zip.AddEntry(RESULT1, pdf);
        zip.AddEntry(RESULT2, metadata.CreatePdfAutomatic());
        byte[] manipulated = metadata.ManipulatePdf(
          new MetadataPdf().CreatePdf()
        );
        zip.AddEntry(RESULT3, manipulated );
        zip.AddEntry(RESULT4, metadata.ReadXmpMetadata(manipulated));
        zip.Save(stream);
      }
    }
// ---------------------------------------------------------------------------
/**
 * Creates a PDF document.
 */
    public byte[] CreatePdf() {
      using (MemoryStream ms = new MemoryStream()) {
        // step 1
        using (Document document = new Document()) {
        // step 2
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          using (MemoryStream msXmp = new MemoryStream()) {
            XmpWriter xmp = new XmpWriter(msXmp);
            XmpSchema dc = new 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();
/*
 *  iTextSharp uses Item property instead of Java setProperty() method
 * 
 *      pdf.SetProperty(PdfSchema.KEYWORDS, "Hello World, XMP, Metadata");
 *      pdf.SetProperty(PdfSchema.VERSION, "1.4");
 */
            pdf[PdfSchema.KEYWORDS] = "Hello World, XMP, Metadata";
            pdf[PdfSchema.VERSION] = "1.4";
            xmp.AddRdfDescription(pdf);
            xmp.Close();
            writer.XmpMetadata = ms.ToArray();
          }
          // step 3
          document.Open();
          // step 4
          document.Add(new Paragraph("Hello World"));
        }
        return ms.ToArray();
      }
    }
// ---------------------------------------------------------------------------  
    /**
     * Creates a PDF document.
     */
    public byte[] CreatePdfAutomatic() {
      using (MemoryStream ms = new MemoryStream()) {
        // step 1
        using (Document document = new Document()) {
          // step 2
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          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"));
        }
        return ms.ToArray();
      }
    }  
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public byte[] ManipulatePdf(byte[] src) {
      PdfReader reader = new PdfReader(src);
      using (MemoryStream ms = new MemoryStream()) {
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          Dictionary info = reader.Info;
          using (MemoryStream msXmp = new MemoryStream()) {
            XmpWriter xmp = new XmpWriter(msXmp, info);
            xmp.Close();
            stamper.XmpMetadata = msXmp.ToArray();      
          }
        }
        return ms.ToArray();
      }
    }      
// ---------------------------------------------------------------------------
    /**
     * Reads the XML stream inside a PDF file into an XML file.
     * @param src  A PDF file containing XMP data
     */
    public string ReadXmpMetadata(byte[] src) {
      PdfReader reader = new PdfReader(src);
      byte[] b = reader.Metadata;
      return Encoding.UTF8.GetString(b, 0, b.Length);
    }  
// ===========================================================================
  }
}
HelloWorldCompression.cs
/*
 * 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.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter12 {
  public class HelloWorldCompression : IWriter {
// ===========================================================================
    /** The resulting PDF file. */
    public const string RESULT1 = "compression_not_at_all.pdf";
    /** The resulting PDF file. */
    public const string RESULT2 = "compression_zero.pdf";
    /** The resulting PDF file. */
    public const string RESULT3 = "compression_normal.pdf";
    /** The resulting PDF file. */
    public const string RESULT4 = "compression_high.pdf";
    /** The resulting PDF file. */
    public const string RESULT5 = "compression_full.pdf";
    /** The resulting PDF file. */
    public const string RESULT6 = "compression_full_too.pdf";
    public const string RESULT7 = "compression_removed.pdf";
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        HelloWorldCompression hello = new HelloWorldCompression();
        zip.AddEntry(RESULT1, hello.CreatePdf(-1));
        byte[] compress0 = hello.CreatePdf(0);
        zip.AddEntry(RESULT2, compress0);
        zip.AddEntry(RESULT3, hello.CreatePdf(1));
        zip.AddEntry(RESULT4, hello.CreatePdf(2));
        zip.AddEntry(RESULT5, hello.CreatePdf(3));
        byte[] compress6 = hello.CompressPdf(compress0);
        zip.AddEntry(RESULT6, compress6);
        zip.AddEntry(RESULT7, hello.DecompressPdf(compress6));
        zip.Save(stream);
      }    
    }
// ---------------------------------------------------------------------------
    /**
     * Creates a PDF with information about the movies
     * @param    filename the name of the PDF file that will be created.
     */
    public byte[] CreatePdf(int compression) {
      using (MemoryStream ms = new MemoryStream()) {
      // step 1
        using (Document document = new Document()) {
        // step 2
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          switch(compression) {
            case -1:
              Document.Compress = false;
              break;
            case 0:
              writer.CompressionLevel = 0;
              break;
            case 2:
              writer.CompressionLevel = 9;
              break;
            case 3:
              writer.SetFullCompression();
              break;
          }
          // step 3
          document.Open();
        // step 4
        // Create database connection and statement
          var SQL = 
@"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);
          DbProviderFactory dbp = AdoDB.Provider;
          using (var c = dbp.CreateConnection()) {
            c.ConnectionString = AdoDB.CS;
            using (DbCommand cmd = c.CreateCommand()) {
              cmd.CommandText = SQL;
              c.Open();            
              using (var r = cmd.ExecuteReader()) {
                while (r.Read()) {
                // create a list item for the country
                  ListItem item = new ListItem(
                    String.Format("{0}: {1} movies", r["country"], r["c"]),
                    FilmFonts.BOLDITALIC
                  );
                  // create a movie list for each country
                  List movielist = new List(List.ORDERED, List.ALPHABETICAL);
                  movielist.Lowercase = List.LOWERCASE;
                  foreach (Movie movie in 
                      PojoFactory.GetMovies(r["country_id"].ToString())) 
                  {
                    ListItem movieitem = new ListItem(movie.MovieTitle);
                    List directorlist = new List(List.UNORDERED);
                    foreach (Director director in movie.Directors) {
                      directorlist.Add(String.Format(
                        "{0}, {1}", director.Name, director.GivenName
                      ));
                    }
                    movieitem.Add(directorlist);
                    movielist.Add(movieitem);
                  }
                  item.Add(movielist);
                  list.Add(item);
                }
              }
            }
          }
          document.Add(list);
        }
        Document.Compress = true; 
        return ms.ToArray();
      }     
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public byte[] CompressPdf(byte[] src) {
      PdfReader reader = new PdfReader(src);
      using (MemoryStream ms = new MemoryStream()) {
        using (PdfStamper stamper = 
            new PdfStamper(reader, ms, PdfWriter.VERSION_1_5))
        {
          stamper.Writer.CompressionLevel = 9;
          int total = reader.NumberOfPages + 1;
          for (int i = 1; i < total; i++) {
            reader.SetPageContent(i, reader.GetPageContent(i));
          }
          stamper.SetFullCompression();
        }
        return ms.ToArray();
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public byte[] DecompressPdf(byte[] src) {
      PdfReader reader = new PdfReader(src);
      using (MemoryStream ms = new MemoryStream()) {
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          Document.Compress = false;
          int total = reader.NumberOfPages + 1;
          for (int i = 1; i < total; i++) {
            reader.SetPageContent(i, reader.GetPageContent(i));
          }
        }
        Document.Compress = true;
        return ms.ToArray();
      }
    }
// ===========================================================================
  }
}
EncryptionPdf.cs
/*
 * 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.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter12 {
  public class EncryptionPdf : IWriter {
// ===========================================================================
    /** User password. */
    public readonly byte[] USER = ASCIIEncoding.UTF8.GetBytes("Hello");
    /** Owner password. */
    public readonly byte[] OWNER = ASCIIEncoding.UTF8.GetBytes("World");

    /** The resulting PDF file. */
    public const string RESULT1 = "encryption.pdf";
    /** The resulting PDF file. */
    public const string RESULT2 = "encryption_decrypted.pdf";
    /** The resulting PDF file. */
    public const string RESULT3 = "encryption_encrypted.pdf";
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        EncryptionPdf metadata = new EncryptionPdf();
        byte[] enc1 = metadata.CreatePdf();        
        zip.AddEntry(RESULT1,enc1);
        byte[] enc2 = metadata.DecryptPdf(enc1);
        zip.AddEntry(RESULT2, enc2);
        zip.AddEntry(RESULT3, metadata.EncryptPdf(enc2));
        zip.Save(stream);
      }    
    }
// ---------------------------------------------------------------------------
    /**
     * Creates a PDF document.
     */
    public byte[] CreatePdf() {
      using (MemoryStream ms = new MemoryStream()) {
      // step 1
        using (Document document = new Document()) {
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          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"));
        }
        return ms.ToArray();
      }    
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public byte[] DecryptPdf(byte[] src) {
      PdfReader reader = new PdfReader(src, OWNER);
      using (MemoryStream ms = new MemoryStream()) {
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
        }
        return ms.ToArray();
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public byte[] EncryptPdf(byte[] src) {
      PdfReader reader = new PdfReader(src);
      using (MemoryStream ms = new MemoryStream()) {
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          stamper.SetEncryption(
            USER, OWNER, 
            PdfWriter.ALLOW_PRINTING, 
            PdfWriter.ENCRYPTION_AES_128 | PdfWriter.DO_NOT_ENCRYPT_METADATA
          );
        }
        return ms.ToArray();
      }
    }    
// ===========================================================================
  }
}
Contact

Still have questions? 

We're happy to answer your questions. Reach out to us and we'll get back to you shortly.

Contact us
Stay updated

Join 11,000+ subscribers and become an iText PDF expert by staying up to date with our new products, updates, tips, technical solutions and happenings.

Subscribe Now