org.faceless.pdf2

## Class PublicKeyEncryptionHandler

- java.lang.Object
- - org.faceless.pdf2.EncryptionHandler
  - - org.faceless.pdf2.PublicKeyEncryptionHandler

- All Implemented Interfaces:
    Cloneable
  Direct Known Subclasses:
    PublicKeyPromptEncryptionHandler

      public class PublicKeyEncryptionHandler
      extends EncryptionHandler

  The PublicKeyEncryptionHandler can be used to encrypt and decrypt documents using public/private key Encryption, so documents can only be opened by certain individuals. It requires Java 1.4 or later, as it uses the `javax.crypto` package. The resulting documents can be opened in Acrobat 5 or later with the appropriate private key.

  We're going to assume you're familiar with public key cryptography if you're using this class, and instead jump straight in and give a couple of examples showing how to decrypt and encrypt a document. First, some important notes:

  1. This handler only works with Java 1.4 or above
  2. You must download and install the unrestricted policy files for the Sun JCE. You can download these from the same place you download Java - for Suns current 1.4.2 release, they are available at http://java.sun.com/j2se/1.4.2/download.html. If they're not installed, you'll see an exception like: `java.lang.SecurityException: Unsupported keysize or algorithm parameters`
  3. You will need a JCE provider that implements the ciphers you need. Any JCE provider should work, including the default Sun JCE provider and the Bouncy Castle provider (available at http://www.bouncycastle.org).

  Once these steps are done, to encrypt a document you need the X.509 certificate of the person you're sending it to. Typically you'd get this from a KeyStore, as in this example:

       KeyStore keystore = KeyStore.getInstance("PKCS12");
       keystore.load(new FileInputStream("keystore.p12"), "password".toCharArray());
       X509Certificate cert = (X509Certificate)keystore.getCertificate("john");

       PublicKeyEncryptionHandler handler = new PublicKeyEncryptionHandler(5);
       handler.addRecipient(cert, StandardEncryptionHandler.PRINT_HIGHRES,
                                  StandardEncryptionHandler.CHANGE_ALL,
                                  StandardEncryptionHandler.EXTRACT_ALL);

       pdf.setEncryptionHandler(handler);

  Other ways to get a certificate include using the `FormSignature.loadPKCS7KeyStore(java.io.InputStream)` method to load your X.509 certificates from a PKCS#7 object, or the `CertificateFactory` class to load the certificate from `.cer` files exported by Acrobat:

       FileInputStream fis = new FileInputStream("certificate.cer");
       CertificateFactory cf = CertificateFactory.getInstance("X.509");
       X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);

  To decrypt a document, you will need a KeyStore containing a private key that matches the public key used to encrypt the document. Typically this will be done like so:

       KeyStore keystore = KeyStore.getInstance("PKCS12");
       keystore.load(new FileInputStream("keystore.p12"), "storepassword".toCharArray());
       EncryptionHandler handler = new PublicKeyEncryptionHandler(keystore,
                                                                  null,
                                                                  "keypassword".toCharArray());

       PDF pdf = new PDF(new PDFReader(new File("encrypted.pdf"), handler));

  Since:
    2.2.5
  See Also:
    `FormSignature`, `PDFReader.PDFReader(InputStream,EncryptionHandler)`, `StandardEncryptionHandler`

- - ### Constructor Summary

    Constructors
    Constructor and Description
    `PublicKeyEncryptionHandler()` Create a new PublicKeyEncryptionHandler for decrypting a document encrypted with the `Adobe.PubSec` public key encryption handler.
    `PublicKeyEncryptionHandler(int acrobatversion)` Create a new PublicKeyEncryptionHandler for encrypting a document.
    `PublicKeyEncryptionHandler(KeyStore keystore, String alias, char[] password)` Create a new PublicKeyEncryptionHandler for decrypting a document encrypted with the `Adobe.PubSec` public key encryption handler.

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `addRecipient(X509Certificate recipient, int print, int extraction, int change)` Add a recipient to the list of people that can open the document
    `protected boolean` | `chooseRecipient(X500Principal[] issuers, BigInteger[] serials)` This method is called by `prepareToDecrypt()` to give an implementation the chance to select an appropriate entry from the KeyStore if it hasn't already been done.
    `void` | `finishedDecrypt()` This method is called after the PDF has been read.
    `void` | `finishedEncrypt()` This method is called after the PDF has been written.
    `int` | `getChange()` Return the value of the "Change" flags.
    `InputStream` | `getDecryptionStream(InputStream in, int num, int gen)` Return a `FilterInputStream` that will decrypt anything read from it.
    `String` | `getDescription()` Return a textual description of the encryption used
    `int` | `getEncryptedStreamLength(int len)` Return the length that a stream of the specified length would be after encryption.
    `OutputStream` | `getEncryptionStream(OutputStream out, int num, int gen)` Return a `FilterOutputStream` that will encrypt anything written to it.
    `int` | `getExtract()` Return the value of the "Extract" flags.
    `String` | `getFilterName()` Return the name of the "Filter" field in the Encryption dictionary.
    `int` | `getPrint()` Return the value of the "Print" flags.
    `String` | `getSubFilterName()` Return the name of the "Subfilter" field in the Encryption dictionary.
    `boolean` | `hasRight(String right)` Returns true if the EncryptionHandler wil grant the specified right to the PDF library.
    `boolean` | `isMetadataEncrypted()` This method returns true if XMP MetaData should be stored encrypted, or false otherwise.
    `boolean` | `isRequired()` This method should return `true` if the document needs to be encrypted.
    `void` | `prepareToDecrypt()` This method is called just before the PDF is read in.
    `void` | `prepareToEncrypt()` This method is called when the PDF is about to be written out.
    `void` | `setDecryptionKey(KeyStore keystore, String alias, char[] password)` Set the private key to use to decrypt the document
    `void` | `setEncryptedMetadata(boolean encrypt)` Set whether XMP Metadata is to be encrypted or not.

    - ### Methods inherited from class org.faceless.pdf2.EncryptionHandler

      `clone, containsKey, getArrayValueSize, getBooleanValue, getDecryptedStreamLength, getDictionaryValueKeys, getFileId, getNameValue, getNumericValue, getStringValue, getTextStringValue, isEmbeddedFileEncrypted, isStreamEncrypted, isStringEncrypted, markChanged, putArrayValue, putBooleanValue, putDictionaryValue, putNameValue, putNumericValue, putStringValue, putTextStringValue, setFileId`

    - ### Methods inherited from class java.lang.Object

      `equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Constructor Detail

    - #### PublicKeyEncryptionHandler

          public PublicKeyEncryptionHandler()

      Create a new PublicKeyEncryptionHandler for decrypting a document encrypted with the `Adobe.PubSec` public key encryption handler. This constructor must be followed by a call to `setDecryptionKey()`.
      Since:
        2.8.2

    - #### PublicKeyEncryptionHandler

          public PublicKeyEncryptionHandler(KeyStore keystore,
                                            String alias,
                                            char[] password)
                                     throws GeneralSecurityException

      Create a new PublicKeyEncryptionHandler for decrypting a document encrypted with the `Adobe.PubSec` public key encryption handler.
      Parameters:
        `keystore` - the KeyStore containing the private key to decrypt the document with
        `alias` - the alias of the key to use, or `null` to use the first key that fits
        `password` - the password to decrypt the private key, or `null` if no password is required
      Throws:
        `GeneralSecurityException`
      Since:
        2.2.5

    - #### PublicKeyEncryptionHandler

          public PublicKeyEncryptionHandler(int acrobatversion)

      Create a new PublicKeyEncryptionHandler for encrypting a document. Recipients can be added using the `addRecipient()` method. The version number specifies the minimum release of Acrobat required to open the document - valid values are from 5 to 8, to target Acrobat 5.0 to 8.0 respectively. Targetting Acrobat 7.0 or above will result in the AES cipher being used if it's available. Targetting earlier version will use the RC4 cipher.
      Parameters:
        `acrobatversion` - the version of Acrobat that is being targeted. Must be between 5 and 8.
      Since:
        2.2.5

  - ### Method Detail

    - #### setEncryptedMetadata

          public void setEncryptedMetadata(boolean encrypt)

      Set whether XMP Metadata is to be encrypted or not. Unencrypted Metadata is supported by Acrobat 6.0 and later.
      Parameters:
        `encrypt` - whether to encrypt the XMP Metadata when saving the file.
      Since:
        2.8.2

    - #### setDecryptionKey

          public void setDecryptionKey(KeyStore keystore,
                                       String alias,
                                       char[] password)
                                throws GeneralSecurityException

      Set the private key to use to decrypt the document
      Parameters:
        `keystore` - the KeyStore containing the private key to decrypt the document with
        `alias` - the alias of the key to use, or `null` to use the first key that fits
        `password` - the password to decrypt the private key, or `null` if no password is required
      Throws:
        `GeneralSecurityException`
      Since:
        2.8.2

    - #### addRecipient

          public void addRecipient(X509Certificate recipient,
                                   int print,
                                   int extraction,
                                   int change)

      Add a recipient to the list of people that can open the document
      Parameters:
        `recipient` - the X.509 certificate of the recipient
        `print` - one of `StandardEncryptionHandler.PRINT_NONE` `StandardEncryptionHandler.PRINT_LOWRES` `StandardEncryptionHandler.PRINT_HIGHRES`
        `extraction` - one of `StandardEncryptionHandler.EXTRACT_NONE` `StandardEncryptionHandler.EXTRACT_ACCESSIBILITY` `StandardEncryptionHandler.EXTRACT_ALL`
        `change` - one of `StandardEncryptionHandler.CHANGE_NONE` `StandardEncryptionHandler.CHANGE_LAYOUT` `StandardEncryptionHandler.CHANGE_FORMS` `StandardEncryptionHandler.CHANGE_ANNOTATIONS` `StandardEncryptionHandler.CHANGE_ALL`
      Since:
        2.2.5

    - #### getChange

          public int getChange()

      Return the value of the "Change" flags. Only valid after decrypting a document.
      Returns:
        one of `StandardEncryptionHandler.CHANGE_NONE` `StandardEncryptionHandler.CHANGE_LAYOUT` `StandardEncryptionHandler.CHANGE_FORMS` `StandardEncryptionHandler.CHANGE_ANNOTATIONS` or `StandardEncryptionHandler.CHANGE_ALL`
      Since:
        2.6.5

    - #### getExtract

          public int getExtract()

      Return the value of the "Extract" flags. Only valid after decrypting a document.
      Returns:
        one of `StandardEncryptionHandler.EXTRACT_NONE` `StandardEncryptionHandler.EXTRACT_ACCESSIBILITY` `StandardEncryptionHandler.EXTRACT_ALL`
      Since:
        2.6.5

    - #### getPrint

          public int getPrint()

      Return the value of the "Print" flags. Only valid after decrypting a document.
      Returns:
        one of `StandardEncryptionHandler.PRINT_NONE` `StandardEncryptionHandler.PRINT_LOWRES` `StandardEncryptionHandler.PRINT_HIGHRES`
      Since:
        2.6.5

    - #### hasRight

          public boolean hasRight(String right)

      Description copied from class: `EncryptionHandler`
      Returns true if the EncryptionHandler wil grant the specified right to the PDF library. The default implementation of this method returns true, but subclasses will override this method based on the rights applied to the document. This method should always return `super.hasRight()` if it doesn't recognise the value of "right"
      Overrides:
        `hasRight` in class `EncryptionHandler`
      Parameters:
        `right` - an interned() String defining the usage right the PDF library is querying.

    - #### getFilterName

          public String getFilterName()

      Description copied from class: `EncryptionHandler`
      Return the name of the "Filter" field in the Encryption dictionary. This is used to determine whether an appropriate filter has been supplied by the decryption process. For example, the `StandardEncryptionHandler` class returns "Standard" from this method.
      Specified by:
        `getFilterName` in class `EncryptionHandler`

    - #### getSubFilterName

          public String getSubFilterName()

      Description copied from class: `EncryptionHandler`
      Return the name of the "Subfilter" field in the Encryption dictionary. This is used to determine whether an appropriate filter has been supplied by the decryption process. As "Subfilter" is an optional field, this method may return `null`.
      Specified by:
        `getSubFilterName` in class `EncryptionHandler`

    - #### getDescription

          public String getDescription()

      Return a textual description of the encryption used
      Since:
        2.8.2

    - #### isRequired

          public boolean isRequired()

      Description copied from class: `EncryptionHandler`
      This method should return `true` if the document needs to be encrypted. For example, the `StandardEncryptionHandler` returns `false` here if and only if no passwords are set and the document is set to allow full access.
      Specified by:
        `isRequired` in class `EncryptionHandler`

    - #### isMetadataEncrypted

          public boolean isMetadataEncrypted()

      Description copied from class: `EncryptionHandler`
      This method returns true if XMP MetaData should be stored encrypted, or false otherwise. The default implementation returns true, subclasses should override as necessary.
      Overrides:
        `isMetadataEncrypted` in class `EncryptionHandler`

    - #### getEncryptedStreamLength

          public int getEncryptedStreamLength(int len)

      Description copied from class: `EncryptionHandler`
      Return the length that a stream of the specified length would be after encryption. Generally this will be the same same as the input length (and that's what this method returns, unless overridden), but for some Encryption algorithms like AES, the size may be rounded up to the nearest block size.
      Overrides:
        `getEncryptedStreamLength` in class `EncryptionHandler`

    - #### getEncryptionStream

          public OutputStream getEncryptionStream(OutputStream out,
                                                  int num,
                                                  int gen)

      Description copied from class: `EncryptionHandler`
      Return a `FilterOutputStream` that will encrypt anything written to it. The encryption parameters are set in `EncryptionHandler.prepareToEncrypt()`, which is called once at the start of the render.
      Specified by:
        `getEncryptionStream` in class `EncryptionHandler`
      Parameters:
        `out` - the OuptutStream that should be written to
        `num` - the object number of the top-level object
        `gen` - the generation number of the top-level object

    - #### getDecryptionStream

          public InputStream getDecryptionStream(InputStream in,
                                                 int num,
                                                 int gen)

      Description copied from class: `EncryptionHandler`
      Return a `FilterInputStream` that will decrypt anything read from it. The decryption parameters are set in `EncryptionHandler.prepareToDecrypt()`, which is called once at the start of the PDF read.
      Specified by:
        `getDecryptionStream` in class `EncryptionHandler`
      Parameters:
        `in` - the InputStream that should be read from
        `num` - the object number of the top-level object
        `gen` - the generation number of the top-level object

    - #### prepareToDecrypt

          public void prepareToDecrypt()
                                throws IOException

      Description copied from class: `EncryptionHandler`
      This method is called just before the PDF is read in. It is expected that this method will read various parameters from the `Encrypt` dictionary by way of the various `get...` methods, and use them and the value of `EncryptionHandler.getFileId()` to set its internal state so that it's ready to start decryption. It may throw an `IOException` if these parameters are invalid, in which case the document cannot be read.
      Specified by:
        `prepareToDecrypt` in class `EncryptionHandler`
      Throws:
        `IOException`

    - #### chooseRecipient

          protected boolean chooseRecipient(X500Principal[] issuers,
                                            BigInteger[] serials)

      This method is called by `prepareToDecrypt()` to give an implementation the chance to select an appropriate entry from the KeyStore if it hasn't already been done. The supplied arrays are equal length and indicate the Issuer and SerialNumber of all the recipients that can decrypt this document. By default this method does nothing.
      Parameters:
        `issuers` - an array listing all the X.509 Certificate Issuers
        `serials` - an array listing all the X.509 Certificate Serial Numbers.
      Returns:
        true if the decryption should continue, false otherwise
      Since:
        2.8.3

    - #### prepareToEncrypt

          public void prepareToEncrypt()
                                throws IOException

      Description copied from class: `EncryptionHandler`
      This method is called when the PDF is about to be written out. It is expected that this method will write various parameters which have been set by the user to the `Encrypt` dictionary (including the "Filter" field) by way of the various `put...` methods, and will use these and the value of `EncryptionHandler.getFileId()` to set its internal state so that it's ready to start encryption. It may throw an `IOException` if these parameters are in any way invalid, in which case the document cannot be written.
      Specified by:
        `prepareToEncrypt` in class `EncryptionHandler`
      Throws:
        `IOException`

    - #### finishedEncrypt

          public void finishedEncrypt()

      Description copied from class: `EncryptionHandler`
      This method is called after the PDF has been written. It may be used to clean up any internal state that needs to be cleaned.
      Specified by:
        `finishedEncrypt` in class `EncryptionHandler`

    - #### finishedDecrypt

          public void finishedDecrypt()

      Description copied from class: `EncryptionHandler`
      This method is called after the PDF has been read. It may be used to clean up any internal state that needs to be cleaned.
      Specified by:
        `finishedDecrypt` in class `EncryptionHandler`

Copyright © 2001-2015 Big Faceless Organization