Class PublicKeyEncryptionHandler
- java.lang.Object
-
- org.faceless.pdf2.EncryptionHandler
-
- org.faceless.pdf2.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 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:
- This handler only works with Java 1.4 or above
- 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
- 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 theCertificateFactory
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(InputStream,EncryptionHandler)
,StandardEncryptionHandler
-
-
Constructor Summary
Constructors Constructor Description PublicKeyEncryptionHandler()
Create a new PublicKeyEncryptionHandler for decrypting a document encrypted with theAdobe.PubSec
public key encryption handler.PublicKeyEncryptionHandler(int acrobatversion)
Create a new PublicKeyEncryptionHandler for encrypting a document.PublicKeyEncryptionHandler(java.security.KeyStore keystore, java.lang.String alias, char[] password)
Create a new PublicKeyEncryptionHandler for decrypting a document encrypted with theAdobe.PubSec
public key encryption handler.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description void
addRecipient(java.security.cert.X509Certificate recipient, int print, int extraction, int change)
Add a recipient to the list of people that can open the documentprotected boolean
chooseRecipient(javax.security.auth.x500.X500Principal[] issuers, java.math.BigInteger[] serials)
This method is called byprepareToDecrypt()
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.java.io.InputStream
getDecryptionStream(java.io.InputStream in, int num, int gen)
Return aFilterInputStream
that will decrypt anything read from it.java.lang.String
getDescription()
Return a textual description of the encryption usedint
getEncryptedStreamLength(int len)
Return the length that a stream of the specified length would be after encryption.java.io.OutputStream
getEncryptionStream(java.io.OutputStream out, int num, int gen)
Return aFilterOutputStream
that will encrypt anything written to it.int
getExtract()
Return the value of the "Extract" flags.java.lang.String
getFilterName()
Return the name of the "Filter" field in the Encryption dictionary.int
getPrint()
Return the value of the "Print" flags.java.lang.String
getSubFilterName()
Return the name of the "Subfilter" field in the Encryption dictionary.boolean
hasRight(java.lang.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 returntrue
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(java.security.KeyStore keystore, java.lang.String alias, char[] password)
Set the private key to use to decrypt the documentvoid
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, getIntegerValue, getNameValue, getNumericValue, getStringValue, getTextStringValue, isChanged, isEmbeddedFileEncrypted, isStreamEncrypted, isStringEncrypted, markChanged, putArrayValue, putBooleanValue, putDictionaryValue, putNameValue, putNumericValue, putStringValue, putTextStringValue, setFileId
-
-
-
-
Constructor Detail
-
PublicKeyEncryptionHandler
public PublicKeyEncryptionHandler()
Create a new PublicKeyEncryptionHandler for decrypting a document encrypted with theAdobe.PubSec
public key encryption handler. This constructor must be followed by a call tosetDecryptionKey()
.- 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 theAdobe.PubSec
public key encryption handler.- Parameters:
keystore
- the KeyStore containing the private key to decrypt the document withalias
- the alias of the key to use, ornull
to use the first key that fitspassword
- the password to decrypt the private key, ornull
if no password is required- Throws:
java.security.GeneralSecurityException
- Since:
- 2.2.5
-
PublicKeyEncryptionHandler
public PublicKeyEncryptionHandler(int acrobatversion)
Create a new PublicKeyEncryptionHandler for encrypting a document. Recipients can be added using theaddRecipient()
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(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 withalias
- the alias of the key to use, ornull
to use the first key that fitspassword
- the password to decrypt the private key, ornull
if no password is required- Throws:
java.security.GeneralSecurityException
- Since:
- 2.8.2
-
addRecipient
public void addRecipient(java.security.cert.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 recipientprint
- one ofStandardEncryptionHandler.PRINT_NONE
StandardEncryptionHandler.PRINT_LOWRES
StandardEncryptionHandler.PRINT_HIGHRES
extraction
- one ofStandardEncryptionHandler.EXTRACT_NONE
StandardEncryptionHandler.EXTRACT_ACCESSIBILITY
StandardEncryptionHandler.EXTRACT_ALL
change
- one ofStandardEncryptionHandler.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.
-
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(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 returnsuper.hasRight()
if it doesn't recognise the value of "right"- Overrides:
hasRight
in classEncryptionHandler
- 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, theStandardEncryptionHandler
class returns "Standard" from this method.- Specified by:
getFilterName
in classEncryptionHandler
-
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 returnnull
.- Specified by:
getSubFilterName
in classEncryptionHandler
-
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 returntrue
if the document needs to be encrypted. For example, theStandardEncryptionHandler
returnsfalse
here if and only if no passwords are set and the document is set to allow full access.- Specified by:
isRequired
in classEncryptionHandler
-
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 classEncryptionHandler
-
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 classEncryptionHandler
-
getEncryptionStream
public java.io.OutputStream getEncryptionStream(java.io.OutputStream out, int num, int gen)
Description copied from class:EncryptionHandler
Return aFilterOutputStream
that will encrypt anything written to it. The encryption parameters are set inEncryptionHandler.prepareToEncrypt()
, which is called once at the start of the render.- Specified by:
getEncryptionStream
in classEncryptionHandler
- Parameters:
out
- the OuptutStream that should be written tonum
- the object number of the top-level objectgen
- 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 aFilterInputStream
that will decrypt anything read from it. The decryption parameters are set inEncryptionHandler.prepareToDecrypt()
, which is called once at the start of the PDF read.- Specified by:
getDecryptionStream
in classEncryptionHandler
- Parameters:
in
- the InputStream that should be read fromnum
- the object number of the top-level objectgen
- 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 theEncrypt
dictionary by way of the variousget...
methods, and use them and the value ofEncryptionHandler.getFileId()
to set its internal state so that it's ready to start decryption. It may throw anIOException
if these parameters are invalid, in which case the document cannot be read.- Specified by:
prepareToDecrypt
in classEncryptionHandler
- Throws:
java.io.IOException
-
chooseRecipient
protected boolean chooseRecipient(javax.security.auth.x500.X500Principal[] issuers, java.math.BigInteger[] serials)
This method is called byprepareToDecrypt()
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 Issuersserials
- 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 theEncrypt
dictionary (including the "Filter" field) by way of the variousput...
methods, and will use these and the value ofEncryptionHandler.getFileId()
to set its internal state so that it's ready to start encryption. It may throw anIOException
if these parameters are in any way invalid, in which case the document cannot be written.- Specified by:
prepareToEncrypt
in classEncryptionHandler
- 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 classEncryptionHandler
-
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 classEncryptionHandler
-
-