]> source.dussan.org Git - poi.git/commitdiff
Support more hashing formats for OOXML protected documents, for bug #55544
authorNick Burch <nick@apache.org>
Wed, 11 Sep 2013 22:22:30 +0000 (22:22 +0000)
committerNick Burch <nick@apache.org>
Wed, 11 Sep 2013 22:22:30 +0000 (22:22 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1522074 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java
src/testcases/org/apache/poi/poifs/crypt/TestEncryptionInfo.java
test-data/openxml4j/EncryptedSHA512.xlsx [deleted file]
test-data/poifs/protected_sha512.xlsx [new file with mode: 0644]

index 21dd25e99ca7131401ce07b7f46c45de2936d4fc..9adec4d6ec5aa1ea4467966a34b652f461be3c45 100644 (file)
@@ -27,8 +27,8 @@ import javax.xml.parsers.DocumentBuilderFactory;
 import org.apache.poi.EncryptedDocumentException;
 
 /**
- *  @author Maxim Valyanskiy
- *  @author Gary King
+ * Reads and processes OOXML Encryption Headers
+ * The constants are largely based on ZIP constants.
  */
 public class EncryptionHeader {
     public static final int ALGORITHM_RC4 = 0x6801;
@@ -36,7 +36,11 @@ public class EncryptionHeader {
     public static final int ALGORITHM_AES_192 = 0x660F;
     public static final int ALGORITHM_AES_256 = 0x6610;
 
+    public static final int HASH_NONE = 0x0000;
     public static final int HASH_SHA1 = 0x8004;
+    public static final int HASH_SHA256 = 0x800C;
+    public static final int HASH_SHA384 = 0x800D;
+    public static final int HASH_SHA512 = 0x800E;
 
     public static final int PROVIDER_RC4 = 1;
     public static final int PROVIDER_AES = 0x18;
@@ -112,9 +116,9 @@ public class EncryptionHeader {
             else if (blockSize == 32)
                 algorithm = ALGORITHM_AES_256;
             else
-                throw new EncryptedDocumentException("Unsupported key length");
+                throw new EncryptedDocumentException("Unsupported key length " + blockSize);
         } else {
-            throw new EncryptedDocumentException("Unsupported cipher");
+            throw new EncryptedDocumentException("Unsupported cipher " + cipher);
         }
 
         String chaining = keyData.getNamedItem("cipherChaining").getNodeValue();
@@ -124,16 +128,28 @@ public class EncryptionHeader {
         else if ("ChainingModeCFB".equals(chaining))
             cipherMode = MODE_CFB;
         else
-            throw new EncryptedDocumentException("Unsupported chaining mode");
+            throw new EncryptedDocumentException("Unsupported chaining mode " + chaining);
 
         String hashAlg = keyData.getNamedItem("hashAlgorithm").getNodeValue();
         int hashSize = Integer.parseInt(keyData.getNamedItem("hashSize")
                                         .getNodeValue());
 
-        if ("SHA1".equals(hashAlg) && hashSize == 20)
+        if ("SHA1".equals(hashAlg) && hashSize == 20) {
             hashAlgorithm = HASH_SHA1;
-        else
-            throw new EncryptedDocumentException("Unsupported hash algorithm");
+        }
+        else if ("SHA256".equals(hashAlg) && hashSize == 32) {
+            hashAlgorithm = HASH_SHA256;
+        }
+        else if ("SHA384".equals(hashAlg) && hashSize == 64) {
+            hashAlgorithm = HASH_SHA384;
+        }
+        else if ("SHA512".equals(hashAlg) && hashSize == 64) {
+            hashAlgorithm = HASH_SHA512;
+        }
+        else {
+            throw new EncryptedDocumentException("Unsupported hash algorithm: " + 
+                                                  hashAlg + " @ " + hashSize + " bytes");
+        }
 
         String salt = keyData.getNamedItem("saltValue").getNodeValue();
         int saltLength = Integer.parseInt(keyData.getNamedItem("saltSize")
index 62607e7e8a71641456bda4eee3a6e1fae751b0fd..098d503dc4cc4ed9185970c5ff4249fd30907668 100644 (file)
@@ -37,9 +37,24 @@ public class TestEncryptionInfo extends TestCase {
         assertEquals(EncryptionHeader.ALGORITHM_AES_128, info.getHeader().getAlgorithm());
         assertEquals(EncryptionHeader.HASH_SHA1, info.getHeader().getHashAlgorithm());
         assertEquals(128, info.getHeader().getKeySize());
+        assertEquals(32, info.getVerifier().getVerifierHash().length);
         assertEquals(EncryptionHeader.PROVIDER_AES, info.getHeader().getProviderType());                
         assertEquals("Microsoft Enhanced RSA and AES Cryptographic Provider", info.getHeader().getCspName());
+    }
+    
+    public void testEncryptionInfoSHA512() throws Exception {
+        POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_sha512.xlsx"));
 
-        assertEquals(32, info.getVerifier().getVerifierHash().length);
+        EncryptionInfo info = new EncryptionInfo(fs);
+
+        assertEquals(4, info.getVersionMajor());
+        assertEquals(4, info.getVersionMinor());
+
+        assertEquals(EncryptionHeader.ALGORITHM_AES_128, info.getHeader().getAlgorithm());
+        assertEquals(EncryptionHeader.HASH_SHA512, info.getHeader().getHashAlgorithm());
+        assertEquals(256, info.getHeader().getKeySize());
+        assertEquals(64, info.getVerifier().getVerifierHash().length);
+        assertEquals(EncryptionHeader.PROVIDER_AES, info.getHeader().getProviderType());                
+//        assertEquals("Microsoft Enhanced RSA and AES Cryptographic Provider", info.getHeader().getCspName());
     }
 }
diff --git a/test-data/openxml4j/EncryptedSHA512.xlsx b/test-data/openxml4j/EncryptedSHA512.xlsx
deleted file mode 100644 (file)
index 1f0ea82..0000000
Binary files a/test-data/openxml4j/EncryptedSHA512.xlsx and /dev/null differ
diff --git a/test-data/poifs/protected_sha512.xlsx b/test-data/poifs/protected_sha512.xlsx
new file mode 100644 (file)
index 0000000..1f0ea82
Binary files /dev/null and b/test-data/poifs/protected_sha512.xlsx differ