You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2014/11/17 11:33:01 UTC
svn commit: r1640137 -
/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java
Author: lehmi
Date: Mon Nov 17 10:33:00 2014
New Revision: 1640137
URL: http://svn.apache.org/r1640137
Log:
PDFBOX-2469: improved decryption handling, fixed checkstyle issues
Modified:
pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java
Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java?rev=1640137&r1=1640136&r2=1640137&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java Mon Nov 17 10:33:00 2014
@@ -32,7 +32,9 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
@@ -52,8 +54,8 @@ import org.apache.pdfbox.exceptions.Wrap
import org.apache.pdfbox.pdmodel.PDDocument;
/**
- * This class represents a security handler as described in the PDF specifications.
- * A security handler is responsible of documents protection.
+ * This class represents a security handler as described in the PDF specifications. A security handler is responsible of
+ * documents protection.
*
* @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
* @author Benoit Guillon (benoit.guillon@snv.jussieu.fr)
@@ -100,10 +102,10 @@ public abstract class SecurityHandler
*/
protected ARCFour rc4 = new ARCFour();
- /**
- * indicates if the Metadata have to be decrypted of not
- */
- protected boolean decryptMetadata;
+ /**
+ * indicates if the Metadata have to be decrypted of not
+ */
+ protected boolean decryptMetadata;
private Set<COSBase> objects = new HashSet<COSBase>();
private Set<COSDictionary> potentialSignatures = new HashSet<COSDictionary>();
@@ -114,8 +116,8 @@ public abstract class SecurityHandler
private boolean aes;
/**
- * The access permission granted to the current user for the document. These
- * permissions are computed during decryption and are in read only mode.
+ * The access permission granted to the current user for the document. These permissions are computed during
+ * decryption and are in read only mode.
*/
protected AccessPermission currentAccessPermission = null;
@@ -123,25 +125,33 @@ public abstract class SecurityHandler
/**
* Prepare the document for encryption.
*
- * @param doc The document that will be encrypted.
+ * @param doc
+ * The document that will be encrypted.
*
- * @throws CryptographyException If there is an error while preparing.
- * @throws IOException If there is an error with the document.
+ * @throws CryptographyException
+ * If there is an error while preparing.
+ * @throws IOException
+ * If there is an error with the document.
*/
public abstract void prepareDocumentForEncryption(PDDocument doc) throws CryptographyException, IOException;
/**
* Prepares everything to decrypt the document.
*
- * If {@link #decryptDocument(PDDocument, DecryptionMaterial)} is used, this method is
- * called from there. Only if decryption of single objects is needed this should be called instead.
- *
- * @param encDictionary encryption dictionary, can be retrieved via {@link PDDocument#getEncryptionDictionary()}
- * @param documentIDArray document id which is returned via {@link COSDocument#getDocumentID()}
- * @param decryptionMaterial Information used to decrypt the document.
+ * If {@link #decryptDocument(PDDocument, DecryptionMaterial)} is used, this method is called from there. Only if
+ * decryption of single objects is needed this should be called instead.
*
- * @throws IOException If there is an error accessing data.
- * @throws CryptographyException If there is an error with decryption.
+ * @param encDictionary
+ * encryption dictionary, can be retrieved via {@link PDDocument#getEncryptionDictionary()}
+ * @param documentIDArray
+ * document id which is returned via {@link COSDocument#getDocumentID()}
+ * @param decryptionMaterial
+ * Information used to decrypt the document.
+ *
+ * @throws IOException
+ * If there is an error accessing data.
+ * @throws CryptographyException
+ * If there is an error with decryption.
*/
public abstract void prepareForDecryption(PDEncryptionDictionary encDictionary, COSArray documentIDArray,
DecryptionMaterial decryptionMaterial) throws CryptographyException, IOException;
@@ -149,20 +159,25 @@ public abstract class SecurityHandler
/**
* Prepare the document for decryption.
*
- * @param doc The document to decrypt.
- * @param mat Information required to decrypt the document.
- * @throws CryptographyException If there is an error while preparing.
- * @throws IOException If there is an error with the document.
+ * @param doc
+ * The document to decrypt.
+ * @param mat
+ * Information required to decrypt the document.
+ * @throws CryptographyException
+ * If there is an error while preparing.
+ * @throws IOException
+ * If there is an error with the document.
*/
public abstract void decryptDocument(PDDocument doc, DecryptionMaterial mat) throws CryptographyException,
IOException;
/**
- * This method must be called by an implementation of this class to really proceed
- * to decryption.
+ * This method must be called by an implementation of this class to really proceed to decryption.
*
- * @throws IOException If there is an error in the decryption.
- * @throws CryptographyException If there is an error in the decryption.
+ * @throws IOException
+ * If there is an error in the decryption.
+ * @throws CryptographyException
+ * If there is an error in the decryption.
*/
protected void proceedDecryption() throws IOException, CryptographyException
{
@@ -223,16 +238,21 @@ public abstract class SecurityHandler
/**
* Encrypt a set of data.
*
- * @param objectNumber The data object number.
- * @param genNumber The data generation number.
- * @param data The data to encrypt.
- * @param output The output to write the encrypted data to.
- * @throws CryptographyException If there is an error during the encryption.
- * @throws IOException If there is an error reading the data.
- * @deprecated While this works fine for RC4 encryption, it will never decrypt AES data
- * You should use encryptData(objectNumber, genNumber, data, output, decrypt)
- * which can do everything. This function is just here for compatibility
- * reasons and will be removed in the future.
+ * @param objectNumber
+ * The data object number.
+ * @param genNumber
+ * The data generation number.
+ * @param data
+ * The data to encrypt.
+ * @param output
+ * The output to write the encrypted data to.
+ * @throws CryptographyException
+ * If there is an error during the encryption.
+ * @throws IOException
+ * If there is an error reading the data.
+ * @deprecated While this works fine for RC4 encryption, it will never decrypt AES data You should use
+ * encryptData(objectNumber, genNumber, data, output, decrypt) which can do everything. This function is
+ * just here for compatibility reasons and will be removed in the future.
*/
public void encryptData(long objectNumber, long genNumber, InputStream data, OutputStream output)
throws CryptographyException, IOException
@@ -244,14 +264,21 @@ public abstract class SecurityHandler
/**
* Encrypt a set of data.
*
- * @param objectNumber The data object number.
- * @param genNumber The data generation number.
- * @param data The data to encrypt.
- * @param output The output to write the encrypted data to.
- * @param decrypt true to decrypt the data, false to encrypt it
- *
- * @throws CryptographyException If there is an error during the encryption.
- * @throws IOException If there is an error reading the data.
+ * @param objectNumber
+ * The data object number.
+ * @param genNumber
+ * The data generation number.
+ * @param data
+ * The data to encrypt.
+ * @param output
+ * The output to write the encrypted data to.
+ * @param decrypt
+ * true to decrypt the data, false to encrypt it
+ *
+ * @throws CryptographyException
+ * If there is an error during the encryption.
+ * @throws IOException
+ * If there is an error reading the data.
*/
public void encryptData(long objectNumber, long genNumber, InputStream data, OutputStream output, boolean decrypt)
throws CryptographyException, IOException
@@ -312,7 +339,14 @@ public abstract class SecurityHandler
byte[] buffer = new byte[256];
for (int n = 0; -1 != (n = data.read(buffer));)
{
- output.write(decryptCipher.update(buffer,0, n ));
+ if (data.available() > 0)
+ {
+ output.write(decryptCipher.update(buffer, 0, n));
+ }
+ else
+ {
+ output.write(decryptCipher.doFinal(buffer, 0, n));
+ }
}
}
catch (InvalidKeyException e)
@@ -331,6 +365,14 @@ public abstract class SecurityHandler
{
throw new WrappedIOException(e);
}
+ catch (IllegalBlockSizeException e)
+ {
+ throw new WrappedIOException(e);
+ }
+ catch (BadPaddingException e)
+ {
+ throw new WrappedIOException(e);
+ }
}
else
{
@@ -344,10 +386,13 @@ public abstract class SecurityHandler
/**
* This will decrypt an object in the document.
*
- * @param object The object to decrypt.
+ * @param object
+ * The object to decrypt.
*
- * @throws CryptographyException If there is an error decrypting the stream.
- * @throws IOException If there is an error getting the stream data.
+ * @throws CryptographyException
+ * If there is an error decrypting the stream.
+ * @throws IOException
+ * If there is an error getting the stream data.
*/
private void decryptObject(COSObject object) throws CryptographyException, IOException
{
@@ -360,12 +405,17 @@ public abstract class SecurityHandler
/**
* This will dispatch to the correct method.
*
- * @param obj The object to decrypt.
- * @param objNum The object number.
- * @param genNum The object generation Number.
- *
- * @throws CryptographyException If there is an error decrypting the stream.
- * @throws IOException If there is an error getting the stream data.
+ * @param obj
+ * The object to decrypt.
+ * @param objNum
+ * The object number.
+ * @param genNum
+ * The object generation Number.
+ *
+ * @throws CryptographyException
+ * If there is an error decrypting the stream.
+ * @throws IOException
+ * If there is an error getting the stream data.
*/
private void decrypt(COSBase obj, long objNum, long genNum) throws CryptographyException, IOException
{
@@ -395,12 +445,17 @@ public abstract class SecurityHandler
/**
* This will decrypt a stream.
*
- * @param stream The stream to decrypt.
- * @param objNum The object number.
- * @param genNum The object generation number.
- *
- * @throws CryptographyException If there is an error getting the stream.
- * @throws IOException If there is an error getting the stream data.
+ * @param stream
+ * The stream to decrypt.
+ * @param objNum
+ * The object number.
+ * @param genNum
+ * The object generation number.
+ *
+ * @throws CryptographyException
+ * If there is an error getting the stream.
+ * @throws IOException
+ * If there is an error getting the stream data.
*/
public void decryptStream(COSStream stream, long objNum, long genNum) throws CryptographyException, IOException
{
@@ -414,16 +469,20 @@ public abstract class SecurityHandler
}
/**
- * This will encrypt a stream, but not the dictionary as the dictionary is
- * encrypted by visitFromString() in COSWriter and we don't want to encrypt
- * it twice.
- *
- * @param stream The stream to decrypt.
- * @param objNum The object number.
- * @param genNum The object generation number.
+ * This will encrypt a stream, but not the dictionary as the dictionary is encrypted by visitFromString() in
+ * COSWriter and we don't want to encrypt it twice.
*
- * @throws CryptographyException If there is an error getting the stream.
- * @throws IOException If there is an error getting the stream data.
+ * @param stream
+ * The stream to decrypt.
+ * @param objNum
+ * The object number.
+ * @param genNum
+ * The object generation number.
+ *
+ * @throws CryptographyException
+ * If there is an error getting the stream.
+ * @throws IOException
+ * If there is an error getting the stream data.
*/
public void encryptStream(COSStream stream, long objNum, long genNum) throws CryptographyException, IOException
{
@@ -434,12 +493,17 @@ public abstract class SecurityHandler
/**
* This will decrypt a dictionary.
*
- * @param dictionary The dictionary to decrypt.
- * @param objNum The object number.
- * @param genNum The object generation number.
- *
- * @throws CryptographyException If there is an error decrypting the document.
- * @throws IOException If there is an error creating a new string.
+ * @param dictionary
+ * The dictionary to decrypt.
+ * @param objNum
+ * The object number.
+ * @param genNum
+ * The object generation number.
+ *
+ * @throws CryptographyException
+ * If there is an error decrypting the document.
+ * @throws IOException
+ * If there is an error creating a new string.
*/
private void decryptDictionary(COSDictionary dictionary, long objNum, long genNum) throws CryptographyException,
IOException
@@ -448,7 +512,8 @@ public abstract class SecurityHandler
{
COSBase value = entry.getValue();
// within a dictionary only the following kind of COS objects have to be decrypted
- if (value instanceof COSString || value instanceof COSStream || value instanceof COSArray || value instanceof COSDictionary)
+ if (value instanceof COSString || value instanceof COSStream || value instanceof COSArray
+ || value instanceof COSDictionary)
{
// if we are a signature dictionary and contain a Contents entry then
// we don't decrypt it.
@@ -464,11 +529,15 @@ public abstract class SecurityHandler
/**
* This will encrypt a string.
*
- * @param string the string to encrypt.
- * @param objNum The object number.
- * @param genNum The object generation number.
+ * @param string
+ * the string to encrypt.
+ * @param objNum
+ * The object number.
+ * @param genNum
+ * The object generation number.
*
- * @throws IOException If an error occurs writing the new string.
+ * @throws IOException
+ * If an error occurs writing the new string.
*/
public void encryptString(COSString string, long objNum, long genNum) throws CryptographyException, IOException
{
@@ -478,16 +547,21 @@ public abstract class SecurityHandler
string.reset();
string.append(buffer.toByteArray());
}
-
+
/**
* This will decrypt a string.
*
- * @param string the string to decrypt.
- * @param objNum The object number.
- * @param genNum The object generation number.
- *
- * @throws CryptographyException If an error occurs during decryption.
- * @throws IOException If an error occurs writing the new string.
+ * @param string
+ * the string to decrypt.
+ * @param objNum
+ * The object number.
+ * @param genNum
+ * The object generation number.
+ *
+ * @throws CryptographyException
+ * If an error occurs during decryption.
+ * @throws IOException
+ * If an error occurs writing the new string.
*/
public void decryptString(COSString string, long objNum, long genNum) throws CryptographyException, IOException
{
@@ -501,12 +575,17 @@ public abstract class SecurityHandler
/**
* This will decrypt an array.
*
- * @param array The array to decrypt.
- * @param objNum The object number.
- * @param genNum The object generation number.
- *
- * @throws CryptographyException If an error occurs during decryption.
- * @throws IOException If there is an error accessing the data.
+ * @param array
+ * The array to decrypt.
+ * @param objNum
+ * The object number.
+ * @param genNum
+ * The object generation number.
+ *
+ * @throws CryptographyException
+ * If an error occurs during decryption.
+ * @throws IOException
+ * If there is an error accessing the data.
*/
public void decryptArray(COSArray array, long objNum, long genNum) throws CryptographyException, IOException
{
@@ -518,7 +597,8 @@ public abstract class SecurityHandler
/**
* Getter of the property <tt>keyLength</tt>.
- * @return Returns the keyLength.
+ *
+ * @return Returns the keyLength.
*/
public int getKeyLength()
{
@@ -528,7 +608,8 @@ public abstract class SecurityHandler
/**
* Setter of the property <tt>keyLength</tt>.
*
- * @param keyLen The keyLength to set.
+ * @param keyLen
+ * The keyLength to set.
*/
public void setKeyLength(int keyLen)
{
@@ -536,8 +617,8 @@ public abstract class SecurityHandler
}
/**
- * Returns the access permissions that were computed during document decryption.
- * The returned object is in read only mode.
+ * Returns the access permissions that were computed during document decryption. The returned object is in read only
+ * mode.
*
* @return the access permissions or null if the document was not decrypted.
*/
@@ -549,7 +630,7 @@ public abstract class SecurityHandler
/**
* True if AES is used for encryption and decryption.
*
- * @return true if AEs is used
+ * @return true if AEs is used
*/
public boolean isAES()
{
@@ -559,7 +640,8 @@ public abstract class SecurityHandler
/**
* Set to true if AES for encryption and decryption should be used.
*
- * @param aesValue if true AES will be used
+ * @param aesValue
+ * if true AES will be used
*
*/
public void setAES(boolean aesValue)