The Apache FOP Project

The Apache™ FOP Project

Apache™ FOP: PDF signing and encryption.

Overview

Apache™ FOP supports encryption of PDF output, thanks to Patrick C. Lankswert and others. This feature is commonly used to prevent unauthorized viewing, printing, editing, copying text from the document and doing annotations. It is also possible to ask the user for a password in order to view the contents. Note that there already exist third party applications which can decrypt an encrypted PDF without effort and allow the aforementioned operations, therefore the degree of protection is limited.

For further information about features and restrictions regarding PDF encryption, look at the documentation coming with Adobe Acrobat or the technical documentation on the Adobe web site.

Signing usage

To sign a PDF you need to generate a pkcs12 file using the openssl command line tool:

openssl req -new -newkey rsa:4096 -nodes -keyout my.key -out my.csr
openssl x509 -req -sha256 -days 365 -in my.csr -signkey my.key -out my.pem
cat my.key my.pem > my2.pem
openssl pkcs12 -export -in my2.pem -out mykeystore.pkcs12 -name myAlias

Add params to the fop.xconf:

<renderer mime="application/pdf">
    <sign-params>
      <keystore>path/mykeystore.pkcs12</keystore>
      <name>your name</name>
      <!-- Below are optional -->
      <location>London UK</location>
      <reason>text</reason>
      <password>pkcs12 password</password>
    </sign-params>
</renderer>

Add these to your classpath or maven pom file:

<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcpkix-jdk15to18</artifactId>
  <version>1.77</version>
</dependency>
<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcprov-jdk15to18</artifactId>
  <version>1.77</version>
</dependency>

Encryption usage (fop.xconf)

<renderer mime="application/pdf">
    <encryption-params>
        <user-password>testuserpass</user-password>
        <owner-password>testownerpass</owner-password>
        <noprint/>
        <nocopy/>
        <noedit/>
        <noannotations/>
        <encryption-length>128</encryption-length>
        <encrypt-metadata>false</encrypt-metadata>
    </encryption-params>
</renderer>

Encryption usage (command line)

Encryption is enabled by supplying any of the encryption related options.

An owner password is set with the -o option. This password is actually used as encryption key. Many tools for PDF processing ask for this password to disregard any restriction imposed on the PDF document.

If no owner password has been supplied but FOP was asked to apply some restrictions, a random password is used. In this case it is obviously impossiible to disregard restrictions in PDF processing tools.

A user password, supplied with the -u option, will cause the PDF display software to ask the reader for this password in order to view the contents of the document. If no user password was supplied, viewing the content is not restricted.

Further restrictions can be imposed by using the following command-line options:

Option Description
-noprint disable printing
-nocopy disable copy/paste of content
-noedit disable editing in Adobe Acrobat
-noannotations disable editing of annotations
-nofillinforms disable filling in forms
-noaccesscontent disable text and graphics extraction for accessibility purposes
-noassembledoc disable assembling documents
-noprinthq disable high quality printing

Encryption usage (embedded)

When FOP is embedded in another Java application you need to set an options map on the renderer. These are the supported options:

Option Description Values Default
encryption-length The encryption length in bit Any multiple of 8 between 40 and 128, or 256 128
ownerPassword The owner password String
userPassword The user password String
allowPrint Allows/disallows printing of the PDF "TRUE" or "FALSE" "TRUE"
allowCopyContent Allows/disallows copy/paste of content "TRUE" or "FALSE" "TRUE"
allowEditContent Allows/disallows editing in Adobe Acrobat "TRUE" or "FALSE" "TRUE"
allowEditAnnotations Allows/disallows editing of annotations "TRUE" or "FALSE" "TRUE"
allowFillInForms Allows/disallows filling in forms "TRUE" or "FALSE" "TRUE"
allowAccessContent Allows/disallows text and graphics extraction for accessibility purposes "TRUE" or "FALSE" "TRUE"
allowAssembleDocument Allows/disallows assembling document "TRUE" or "FALSE" "TRUE"
allowPrintHq Allows/disallows high quality printing "TRUE" or "FALSE" "TRUE"
encrypt-metadata Whether to encrypt the Metadata stream "TRUE" or "FALSE" "TRUE"

Encryption is enabled as soon as one of these options is set.

An example to enable PDF encryption in Java code:

import org.apache.fop.pdf.PDFEncryptionParams;

[..]

FOUserAgent userAgent = fopFactory.newFOUserAgent();
userAgent.getRendererOptions().put("encryption-params", new PDFEncryptionParams(
    null, "password", false, false, true, true, true));
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent);
[..]

The parameters for the constructor of PDFEncryptionParams are:

  1. userPassword: String, may be null

  2. ownerPassword: String, may be null

  3. allowPrint: true if printing is allowed

  4. allowCopyContent: true if copying content is allowed

  5. allowEditContent: true if editing content is allowed

  6. allowEditAnnotations: true if editing annotations is allowed

  7. allowFillInForms: true if filling in forms is allowed.

  8. allowAccessContent: true if extracting text and graphics is allowed

  9. allowAssembleDocument: true if assembling document is allowed

  10. allowPrintHq: true if printing to high quality is allowed

  11. encryptMetadata: true if the Metadata stream should be encrypted

Alternatively, you can set each value separately in the Map provided by FOUserAgent.getRendererOptions() by using the following keys:

  1. user-password: String

  2. owner-password: String

  3. noprint: Boolean or "true"/"false"

  4. nocopy: Boolean or "true"/"false"

  5. noedit: Boolean or "true"/"false"

  6. noannotations: Boolean or "true"/"false"

  7. nofillinforms: Boolean or "true"/"false"

  8. noaccesscontent: Boolean or "true"/"false"

  9. noassembledoc: Boolean or "true"/"false"

  10. noprinthq: Boolean or "true"/"false"

  11. encrypt-metadata: Boolean or "true"/"false"

The password length is restricted to a maximum of 32 bytes if the encryption-length is 128 or less, and to a maximum of 127 bytes if the encryption-length is 256 (longer passwords will be truncated to the maximum allowed).

Environment

The PDF encryption implemented in FOP does not need external libraries to perform encryption. A recent JDK (1.5+) is sufficient. However, encryption using keys with 256 bits requires the installation of the JCE Unlimited Strength Jurisdiction Policy files from Oracle.