]> source.dussan.org Git - poi.git/commitdiff
Fix zero-padding and handling of empty passwords (meaning protection on, but no passw...
authorDavid North <dnorth@apache.org>
Mon, 1 Aug 2016 12:51:24 +0000 (12:51 +0000)
committerDavid North <dnorth@apache.org>
Mon, 1 Aug 2016 12:51:24 +0000 (12:51 +0000)
https://bz.apache.org/bugzilla/show_bug.cgi?id=59920

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1754744 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/poifs/crypt/CryptoFunctions.java
src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFPaswordHelper.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java

index f681f3ad1e5f94aab56d39c5f297ae1232509221..69f8d6768be62609c66a74503db01ceb1d0ccf02 100644 (file)
@@ -374,20 +374,22 @@ public class CryptoFunctions {
         // SET Verifier TO 0x0000\r
         short verifier = 0;\r
 \r
-        // FOR EACH PasswordByte IN PasswordArray IN REVERSE ORDER\r
-        for (int i = arrByteChars.length-1; i >= 0; i--) {\r
-            // SET Verifier TO Intermediate3 BITWISE XOR PasswordByte\r
+        if (!"".equals(password)) {\r
+            // FOR EACH PasswordByte IN PasswordArray IN REVERSE ORDER\r
+            for (int i = arrByteChars.length-1; i >= 0; i--) {\r
+                // SET Verifier TO Intermediate3 BITWISE XOR PasswordByte\r
+                verifier = rotateLeftBase15Bit(verifier);\r
+                verifier ^= arrByteChars[i];\r
+            }\r
+    \r
+            // as we haven't prepended the password length into the input array\r
+            // we need to do it now separately ...\r
             verifier = rotateLeftBase15Bit(verifier);\r
-            verifier ^= arrByteChars[i];\r
+            verifier ^= arrByteChars.length;\r
+            \r
+            // RETURN Verifier BITWISE XOR 0xCE4B\r
+            verifier ^= 0xCE4B; // (0x8000 | ('N' << 8) | 'K')\r
         }\r
-\r
-        // as we haven't prepended the password length into the input array\r
-        // we need to do it now separately ...\r
-        verifier = rotateLeftBase15Bit(verifier);\r
-        verifier ^= arrByteChars.length;\r
-        \r
-        // RETURN Verifier BITWISE XOR 0xCE4B\r
-        verifier ^= 0xCE4B; // (0x8000 | ('N' << 8) | 'K')\r
         \r
         return verifier & 0xFFFF;\r
     }\r
index c910499485aae5a2f2fbdbf45627c836d18b8d8f..fd6e2dbd04abc6fe153f4adb3300330803726b1d 100644 (file)
@@ -55,8 +55,8 @@ public class XSSFPaswordHelper {
         cur.toFirstContentToken();\r
         if (hashAlgo == null) {\r
             int hash = CryptoFunctions.createXorVerifier1(password);\r
-            cur.insertAttributeWithValue(getAttrName(prefix, "password"), \r
-                                         Integer.toHexString(hash).toUpperCase(Locale.ROOT));\r
+            cur.insertAttributeWithValue(getAttrName(prefix, "password"),\r
+                                         String.format(Locale.ROOT, "%04X", hash).toUpperCase(Locale.ROOT));\r
         } else {\r
             SecureRandom random = new SecureRandom(); \r
             byte salt[] = random.generateSeed(16);\r
index a9b0d1f0b5b4c28cba2e4bcec37c0f47c26270d6..689e999bcbe9f82bd17eaffe08a643544be15f89 100644 (file)
@@ -80,6 +80,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCalcMode;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnsignedShortHex;
 
 
 public final class TestXSSFSheet extends BaseTestXSheet {
@@ -1099,6 +1100,30 @@ public final class TestXSSFSheet extends BaseTestXSheet {
         wb.close();
     }
 
+    @Test
+    public void protectSheet_emptyPassword() throws IOException {
+        XSSFWorkbook wb = new XSSFWorkbook();
+        XSSFSheet sheet = wb.createSheet();
+        CTSheetProtection pr = sheet.getCTWorksheet().getSheetProtection();
+        assertNull("CTSheetProtection should be null by default", pr);
+        String password = "";
+        sheet.protectSheet(password);
+        pr = sheet.getCTWorksheet().getSheetProtection();
+        assertNotNull("CTSheetProtection should be not null", pr);
+        assertTrue("sheet protection should be on", pr.isSetSheet());
+        assertTrue("object protection should be on", pr.isSetObjects());
+        assertTrue("scenario protection should be on", pr.isSetScenarios());
+        int hashVal = CryptoFunctions.createXorVerifier1(password);
+        STUnsignedShortHex xpassword = pr.xgetPassword();
+        int actualVal = Integer.parseInt(xpassword.getStringValue(),16);
+        assertEquals("well known value for top secret hash should match", hashVal, actualVal);
+
+        sheet.protectSheet(null);
+        assertNull("protectSheet(null) should unset CTSheetProtection", sheet.getCTWorksheet().getSheetProtection());
+
+        wb.close();
+    }
+
     @Test
     public void protectSheet_lowlevel_2013() throws IOException {
         String password = "test";