mirror of https://github.com/apache/poi.git
Fix zero-padding and handling of empty passwords (meaning protection on, but no password to remove it) for XSSF workbook protection.
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
This commit is contained in:
parent
9c591aa822
commit
22623b78bc
|
@ -374,20 +374,22 @@ public class CryptoFunctions {
|
||||||
// SET Verifier TO 0x0000
|
// SET Verifier TO 0x0000
|
||||||
short verifier = 0;
|
short verifier = 0;
|
||||||
|
|
||||||
// FOR EACH PasswordByte IN PasswordArray IN REVERSE ORDER
|
if (!"".equals(password)) {
|
||||||
for (int i = arrByteChars.length-1; i >= 0; i--) {
|
// FOR EACH PasswordByte IN PasswordArray IN REVERSE ORDER
|
||||||
// SET Verifier TO Intermediate3 BITWISE XOR PasswordByte
|
for (int i = arrByteChars.length-1; i >= 0; i--) {
|
||||||
|
// SET Verifier TO Intermediate3 BITWISE XOR PasswordByte
|
||||||
|
verifier = rotateLeftBase15Bit(verifier);
|
||||||
|
verifier ^= arrByteChars[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// as we haven't prepended the password length into the input array
|
||||||
|
// we need to do it now separately ...
|
||||||
verifier = rotateLeftBase15Bit(verifier);
|
verifier = rotateLeftBase15Bit(verifier);
|
||||||
verifier ^= arrByteChars[i];
|
verifier ^= arrByteChars.length;
|
||||||
|
|
||||||
|
// RETURN Verifier BITWISE XOR 0xCE4B
|
||||||
|
verifier ^= 0xCE4B; // (0x8000 | ('N' << 8) | 'K')
|
||||||
}
|
}
|
||||||
|
|
||||||
// as we haven't prepended the password length into the input array
|
|
||||||
// we need to do it now separately ...
|
|
||||||
verifier = rotateLeftBase15Bit(verifier);
|
|
||||||
verifier ^= arrByteChars.length;
|
|
||||||
|
|
||||||
// RETURN Verifier BITWISE XOR 0xCE4B
|
|
||||||
verifier ^= 0xCE4B; // (0x8000 | ('N' << 8) | 'K')
|
|
||||||
|
|
||||||
return verifier & 0xFFFF;
|
return verifier & 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,8 +55,8 @@ public class XSSFPaswordHelper {
|
||||||
cur.toFirstContentToken();
|
cur.toFirstContentToken();
|
||||||
if (hashAlgo == null) {
|
if (hashAlgo == null) {
|
||||||
int hash = CryptoFunctions.createXorVerifier1(password);
|
int hash = CryptoFunctions.createXorVerifier1(password);
|
||||||
cur.insertAttributeWithValue(getAttrName(prefix, "password"),
|
cur.insertAttributeWithValue(getAttrName(prefix, "password"),
|
||||||
Integer.toHexString(hash).toUpperCase(Locale.ROOT));
|
String.format(Locale.ROOT, "%04X", hash).toUpperCase(Locale.ROOT));
|
||||||
} else {
|
} else {
|
||||||
SecureRandom random = new SecureRandom();
|
SecureRandom random = new SecureRandom();
|
||||||
byte salt[] = random.generateSeed(16);
|
byte salt[] = random.generateSeed(16);
|
||||||
|
|
|
@ -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.CTXf;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCalcMode;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCalcMode;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnsignedShortHex;
|
||||||
|
|
||||||
|
|
||||||
public final class TestXSSFSheet extends BaseTestXSheet {
|
public final class TestXSSFSheet extends BaseTestXSheet {
|
||||||
|
@ -1099,6 +1100,30 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
||||||
wb.close();
|
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
|
@Test
|
||||||
public void protectSheet_lowlevel_2013() throws IOException {
|
public void protectSheet_lowlevel_2013() throws IOException {
|
||||||
String password = "test";
|
String password = "test";
|
||||||
|
|
Loading…
Reference in New Issue