You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2015/02/20 17:58:52 UTC
svn commit: r1661161 -
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java
Author: tilman
Date: Fri Feb 20 16:58:51 2015
New Revision: 1661161
URL: http://svn.apache.org/r1661161
Log:
PDFBOX-2576: use constant; split long method
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java?rev=1661161&r1=1661160&r2=1661161&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java Fri Feb 20 16:58:51 2015
@@ -20,6 +20,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
+import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -72,6 +73,8 @@ public final class StandardSecurityHandl
// hashes used for Algorithm 2.B, depending on remainder from E modulo 3
private static final String[] HASHES_2B = new String[] {"SHA-256", "SHA-384", "SHA-512"};
+ private static final Charset ISO_8859_1_CHARSET = Charset.forName("ISO-8859-1");
+
private static final int DEFAULT_VERSION = 1;
private StandardProtectionPolicy policy;
@@ -175,18 +178,7 @@ public final class StandardSecurityHandl
int dicRevision = encryption.getRevision();
int dicLength = encryption.getVersion() == 1 ? 5 : encryption.getLength() / 8;
- //some documents may have not document id, see
- //test\encryption\encrypted_doc_no_id.pdf
- byte[] documentIDBytes;
- if( documentIDArray != null && documentIDArray.size() >= 1 )
- {
- COSString id = (COSString)documentIDArray.getObject( 0 );
- documentIDBytes = id.getBytes();
- }
- else
- {
- documentIDBytes = new byte[0];
- }
+ byte[] documentIDBytes = getDocumentIDBytes(documentIDArray);
// we need to know whether the meta data was encrypted for password calculation
boolean encryptMetadata = encryption.isEncryptMetaData();
@@ -195,10 +187,10 @@ public final class StandardSecurityHandl
byte[] ownerKey = encryption.getOwnerKey();
byte[] ue = null, oe = null;
- String passwordCharset = "ISO-8859-1";
+ Charset passwordCharset = ISO_8859_1_CHARSET;
if (dicRevision == 6 || dicRevision == 5)
{
- passwordCharset = "UTF-8";
+ passwordCharset = Charset.forName("UTF-8");
ue = encryption.getUserEncryptionKey();
oe = encryption.getOwnerEncryptionKey();
}
@@ -252,37 +244,7 @@ public final class StandardSecurityHandl
if (dicRevision == 6 || dicRevision == 5)
{
- // Algorithm 13: validate permissions ("Perms" field). Relaxed to accomodate buggy encoders
- try
- {
- Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
- cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(encryptionKey, "AES"));
- byte[] perms = cipher.doFinal(encryption.getPerms());
-
- if (perms[9] != 'a' || perms[10] != 'd' || perms[11] != 'b')
- {
- LOG.warn("Verification of permissions failed (constant)");
- }
-
- int permsP = perms[0] & 0xFF | perms[1] & 0xFF << 8 | perms[2] & 0xFF << 16 |
- perms[3] & 0xFF << 24;
-
- if (permsP != dicPermissions)
- {
- LOG.warn("Verification of permissions failed (" + permsP +
- " != " + dicPermissions + ")");
- }
-
- if (encryptMetadata && perms[8] != 'T' || !encryptMetadata && perms[8] != 'F')
- {
- LOG.warn("Verification of permissions failed (EncryptMetadata)");
- }
- }
- catch (GeneralSecurityException e)
- {
- logIfStrongEncryptionMissing();
- throw new IOException(e);
- }
+ validatePerms(encryption, dicPermissions, encryptMetadata);
}
// detect whether AES encryption is used. This assumes that the encryption algo is
@@ -299,6 +261,58 @@ public final class StandardSecurityHandl
}
}
}
+
+ private byte[] getDocumentIDBytes(COSArray documentIDArray)
+ {
+ //some documents may not have document id, see
+ //test\encryption\encrypted_doc_no_id.pdf
+ byte[] documentIDBytes;
+ if( documentIDArray != null && documentIDArray.size() >= 1 )
+ {
+ COSString id = (COSString)documentIDArray.getObject( 0 );
+ documentIDBytes = id.getBytes();
+ }
+ else
+ {
+ documentIDBytes = new byte[0];
+ }
+ return documentIDBytes;
+ }
+
+ // Algorithm 13: validate permissions ("Perms" field). Relaxed to accomodate buggy encoders
+ private void validatePerms(PDEncryption encryption, int dicPermissions, boolean encryptMetadata) throws IOException
+ {
+ try
+ {
+ Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
+ cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(encryptionKey, "AES"));
+ byte[] perms = cipher.doFinal(encryption.getPerms());
+
+ if (perms[9] != 'a' || perms[10] != 'd' || perms[11] != 'b')
+ {
+ LOG.warn("Verification of permissions failed (constant)");
+ }
+
+ int permsP = perms[0] & 0xFF | perms[1] & 0xFF << 8 | perms[2] & 0xFF << 16 |
+ perms[3] & 0xFF << 24;
+
+ if (permsP != dicPermissions)
+ {
+ LOG.warn("Verification of permissions failed (" + permsP +
+ " != " + dicPermissions + ")");
+ }
+
+ if (encryptMetadata && perms[8] != 'T' || !encryptMetadata && perms[8] != 'F')
+ {
+ LOG.warn("Verification of permissions failed (EncryptMetadata)");
+ }
+ }
+ catch (GeneralSecurityException e)
+ {
+ logIfStrongEncryptionMissing();
+ throw new IOException(e);
+ }
+ }
/**
* Prepare document for encryption.
@@ -447,11 +461,11 @@ public final class StandardSecurityHandl
MessageDigest md = MessageDigests.getMD5();
BigInteger time = BigInteger.valueOf( System.currentTimeMillis() );
md.update( time.toByteArray() );
- md.update( ownerPassword.getBytes("ISO-8859-1") );
- md.update( userPassword.getBytes("ISO-8859-1") );
+ md.update( ownerPassword.getBytes(ISO_8859_1_CHARSET) );
+ md.update( userPassword.getBytes(ISO_8859_1_CHARSET) );
md.update( document.getDocument().toString().getBytes() );
- byte[] id = md.digest( this.toString().getBytes("ISO-8859-1") );
+ byte[] id = md.digest( this.toString().getBytes(ISO_8859_1_CHARSET) );
COSString idString = new COSString(id);
idArray = new COSArray();
@@ -463,14 +477,14 @@ public final class StandardSecurityHandl
COSString id = (COSString)idArray.getObject( 0 );
byte[] ownerBytes = computeOwnerPassword(
- ownerPassword.getBytes("ISO-8859-1"),
- userPassword.getBytes("ISO-8859-1"), revision, length);
+ ownerPassword.getBytes(ISO_8859_1_CHARSET),
+ userPassword.getBytes(ISO_8859_1_CHARSET), revision, length);
byte[] userBytes = computeUserPassword(
- userPassword.getBytes("ISO-8859-1"),
+ userPassword.getBytes(ISO_8859_1_CHARSET),
ownerBytes, permissionInt, id.getBytes(), revision, length, true);
- encryptionKey = computeEncryptedKey(userPassword.getBytes("ISO-8859-1"), ownerBytes,
+ encryptionKey = computeEncryptedKey(userPassword.getBytes(ISO_8859_1_CHARSET), ownerBytes,
null, null, null, permissionInt, id.getBytes(), revision, length, true, false);
encryptionDictionary.setOwnerKey(ownerBytes);
@@ -928,7 +942,7 @@ public final class StandardSecurityHandl
}
else
{
- return isUserPassword(password.getBytes("ISO-8859-1"), user, owner, permissions, id,
+ return isUserPassword(password.getBytes(ISO_8859_1_CHARSET), user, owner, permissions, id,
encRevision, length, encryptMetadata);
}
}
@@ -953,7 +967,7 @@ public final class StandardSecurityHandl
byte[] id, int encRevision, int length, boolean encryptMetadata)
throws IOException
{
- return isOwnerPassword(password.getBytes("ISO-8859-1"), user,owner,permissions, id,
+ return isOwnerPassword(password.getBytes(ISO_8859_1_CHARSET), user,owner,permissions, id,
encRevision, length, encryptMetadata);
}