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);
     }