Class PublicKeyEncryptionHandler

  • All Implemented Interfaces:
    java.lang.Cloneable

    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 someone in posession of the private key. This form of encryption requires key management so is not as widely supported as password encryption, however dedicated PDF viewers (including Acrobat and Foxit) should support it.

    To encrypt a document you need the X.509 certificates of the recipients - multiple recipients are allowed. RSA and (since 2.28.5) Elliptic Curve keys are supported.

    Typically you'd get this from 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(PublicKeyEncryptionHandler.METHOD_AES256);
     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 a public key used to encrypt the document.

     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:
    PDFReader(InputStream,EncryptionHandler), StandardEncryptionHandler
    • Field Detail

      • METHOD_RC4_3DES128_OLD

        public static final int METHOD_RC4_3DES128_OLD
        A constant that can be passed to the constructor to encrypt using the 128-bit RC4/3DES ciphers and the original method defined in PDF 1.4 and supported in Acrobat 5.
        Since:
        2.2.5, with the constant added in 2.28.5
        See Also:
        Constant Field Values
      • METHOD_RC4_3DES128

        public static final int METHOD_RC4_3DES128
        A constant that can be passed to the constructor to encrypt using the 128-bit RC4/3DES ciphers defined in PDF 1.5 and supported in Acrobat 6 First added to the API in 2.2.5
        Since:
        2.2.5, with the constant added in 2.28.5
        See Also:
        Constant Field Values
      • METHOD_AES128

        public static final int METHOD_AES128
        A constant that can be passed to the constructor to encrypt using the 128-bit AES ciphers defined in PDF 1.6 and supported in Acrobat 7 First added to the API in 2.8.2
        Since:
        2.8.2, with the constant added in 2.28.5
        See Also:
        Constant Field Values
      • METHOD_AES256

        public static final int METHOD_AES256
        A constant that can be passed to the constructor to encrypt using the 256-bit AES ciphers defined in PDF 2.0 (ISO 32000-2)
        Since:
        2.28.5
        See Also:
        Constant Field Values
      • METHOD_AES256_GCM

        public static final int METHOD_AES256_GCM
        A constant that can be passed to the constructor to encrypt using the 256-bit AES ciphers in Galois Counter Mode, defined in ISO 32003.
        Since:
        2.28.5
        See Also:
        Constant Field Values
    • 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​(java.security.KeyStore keystore,
                                          java.lang.String alias,
                                          char[] password)
                                   throws java.security.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:
        java.security.GeneralSecurityException
        Since:
        2.2.5
      • PublicKeyEncryptionHandler

        public PublicKeyEncryptionHandler​(int method)
        Create a new PublicKeyEncryptionHandler for encrypting a document. Recipients can be added using the addRecipient() method. The parameter should be one of the METHOD constants defined in this class (prior to release 2.28.5 the supplied value was an "acrobat version number", but it has been redefined using these constants)
        Parameters:
        method - one of METHOD_RC4_3DES128_OLD, METHOD_RC4_3DES128, METHOD_AES128, METHOD_AES256 or METHOD_AES256_GCM
        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​(java.security.KeyStore keystore,
                                     java.lang.String alias,
                                     char[] password)
                              throws java.security.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:
        java.security.GeneralSecurityException
        Since:
        2.8.2
      • setDecryptionKey

        public void setDecryptionKey​(java.security.KeyStore keystore,
                                     java.lang.String alias,
                                     java.security.KeyStore.ProtectionParameter protection)
                              throws java.security.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
        protection - the KeyStore.ProtectionParameter used to decrypt the password
        Throws:
        java.security.GeneralSecurityException
        Since:
        2.28.5
      • hasRight

        public boolean hasRight​(java.lang.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 java.lang.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 java.lang.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 java.lang.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 java.io.OutputStream getEncryptionStream​(java.io.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 java.io.InputStream getDecryptionStream​(java.io.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 java.io.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:
        java.io.IOException
      • chooseRecipient

        protected boolean chooseRecipient​(javax.security.auth.x500.X500Principal[] issuers,
                                          java.math.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 java.io.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:
        java.io.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