mirror of https://github.com/apache/poi.git
#65192 - Allow change of EncryptionMode
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1887764 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
393d3a3ce9
commit
2ceb5ff553
|
@ -271,7 +271,8 @@ public abstract class POIDocument implements Closeable {
|
|||
*/
|
||||
protected void writeProperties(POIFSFileSystem outFS, List<String> writtenEntries) throws IOException {
|
||||
final EncryptionInfo ei = getEncryptionInfo();
|
||||
final boolean encryptProps = (ei != null && ei.isDocPropsEncrypted());
|
||||
Encryptor encGen = (ei == null) ? null : ei.getEncryptor();
|
||||
final boolean encryptProps = (ei != null && ei.isDocPropsEncrypted() && encGen instanceof CryptoAPIEncryptor);
|
||||
try (POIFSFileSystem tmpFS = new POIFSFileSystem()) {
|
||||
final POIFSFileSystem fs = (encryptProps) ? tmpFS : outFS;
|
||||
|
||||
|
@ -282,6 +283,8 @@ public abstract class POIDocument implements Closeable {
|
|||
return;
|
||||
}
|
||||
|
||||
// Only CryptoAPI encryption supports encrypted property sets
|
||||
|
||||
// create empty document summary
|
||||
writePropertySet(DocumentSummaryInformation.DEFAULT_STREAM_NAME, newDocumentSummaryInformation(), outFS);
|
||||
|
||||
|
@ -289,11 +292,6 @@ public abstract class POIDocument implements Closeable {
|
|||
if (outFS.getRoot().hasEntry(SummaryInformation.DEFAULT_STREAM_NAME)) {
|
||||
outFS.getRoot().getEntry(SummaryInformation.DEFAULT_STREAM_NAME).delete();
|
||||
}
|
||||
Encryptor encGen = ei.getEncryptor();
|
||||
if (!(encGen instanceof CryptoAPIEncryptor)) {
|
||||
throw new EncryptedDocumentException(
|
||||
"Using " + ei.getEncryptionMode() + " encryption. Only CryptoAPI encryption supports encrypted property sets!");
|
||||
}
|
||||
CryptoAPIEncryptor enc = (CryptoAPIEncryptor) encGen;
|
||||
try {
|
||||
enc.setSummaryEntries(outFS.getRoot(), getEncryptedPropertyStreamName(), fs);
|
||||
|
|
|
@ -2255,4 +2255,46 @@ public final class HSSFWorkbook extends POIDocument implements Workbook {
|
|||
public HSSFEvaluationWorkbook createEvaluationWorkbook() {
|
||||
return HSSFEvaluationWorkbook.create(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the encryption mode - if not set, defaults to {@link EncryptionMode#cryptoAPI}.
|
||||
* Allowed modes are {@code null} = remove encryption - same as {@code Biff8EncryptionKey.setCurrentUserPassword(null)},
|
||||
* {@link EncryptionMode#cryptoAPI}, {@link EncryptionMode#binaryRC4}, {@link EncryptionMode#xor}.
|
||||
* Use {@link EncryptionMode#binaryRC4} for Libre Office, but better use OOXML format/encryption for real security.
|
||||
*
|
||||
* @param mode the encryption mode
|
||||
*/
|
||||
public void setEncryptionMode(EncryptionMode mode) {
|
||||
if (mode == null) {
|
||||
Biff8EncryptionKey.setCurrentUserPassword(null);
|
||||
return;
|
||||
}
|
||||
if (mode != EncryptionMode.xor && mode != EncryptionMode.binaryRC4 && mode != EncryptionMode.cryptoAPI) {
|
||||
throw new IllegalArgumentException("Only xor, binaryRC4 and cryptoAPI are supported.");
|
||||
}
|
||||
|
||||
FilePassRecord oldFPR = (FilePassRecord)getInternalWorkbook().findFirstRecordBySid(FilePassRecord.sid);
|
||||
EncryptionMode oldMode = (oldFPR == null) ? null : oldFPR.getEncryptionInfo().getEncryptionMode();
|
||||
if (mode == oldMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Properties need to be cached, when we change the encryption mode
|
||||
readProperties();
|
||||
WorkbookRecordList wrl = getInternalWorkbook().getWorkbookRecordList();
|
||||
if (oldFPR != null) {
|
||||
wrl.remove(oldFPR);
|
||||
}
|
||||
|
||||
FilePassRecord newFPR = new FilePassRecord(mode);
|
||||
wrl.add(1, newFPR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the encryption mode or {@code null} if unset
|
||||
*/
|
||||
public EncryptionMode getEncryptionMode() {
|
||||
FilePassRecord r = (FilePassRecord)getInternalWorkbook().findFirstRecordBySid(FilePassRecord.sid);
|
||||
return (r == null) ? null : r.getEncryptionInfo().getEncryptionMode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,23 +23,34 @@ import static org.apache.poi.POIDataSamples.getSpreadSheetInstance;
|
|||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.poi.hssf.model.WorkbookRecordList;
|
||||
import org.apache.poi.hssf.record.FilePassRecord;
|
||||
|
||||
import org.apache.poi.POIDataSamples;
|
||||
import org.apache.poi.POIDocument;
|
||||
import org.apache.poi.extractor.ExtractorFactory;
|
||||
import org.apache.poi.extractor.POITextExtractor;
|
||||
import org.apache.poi.hssf.record.Record;
|
||||
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.poifs.crypt.EncryptionInfo;
|
||||
import org.apache.poi.poifs.crypt.EncryptionMode;
|
||||
import org.apache.poi.poifs.crypt.binaryrc4.BinaryRC4EncryptionHeader;
|
||||
import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionHeader;
|
||||
import org.apache.poi.poifs.storage.RawDataUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
@ -167,4 +178,38 @@ class TestHxxFEncryption {
|
|||
Biff8EncryptionKey.setCurrentUserPassword(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changeEncryptionMode() throws IOException {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream(10_000);
|
||||
|
||||
try (HSSFWorkbook wb = new HSSFWorkbook()) {
|
||||
wb.createSheet().createRow(1).createCell(1).setCellValue("Test");
|
||||
Biff8EncryptionKey.setCurrentUserPassword("test1");
|
||||
wb.write(bos);
|
||||
}
|
||||
|
||||
try (HSSFWorkbook wb = new HSSFWorkbook(new ByteArrayInputStream(bos.toByteArray()))) {
|
||||
assertEquals(EncryptionMode.cryptoAPI, wb.getEncryptionMode());
|
||||
wb.setEncryptionMode(EncryptionMode.binaryRC4);
|
||||
Biff8EncryptionKey.setCurrentUserPassword("test2");
|
||||
bos.reset();
|
||||
wb.write(bos);
|
||||
}
|
||||
|
||||
try (HSSFWorkbook wb = new HSSFWorkbook(new ByteArrayInputStream(bos.toByteArray()))) {
|
||||
assertEquals(EncryptionMode.binaryRC4, wb.getEncryptionMode());
|
||||
wb.setEncryptionMode(null);
|
||||
bos.reset();
|
||||
wb.write(bos);
|
||||
}
|
||||
|
||||
assertNull(Biff8EncryptionKey.getCurrentUserPassword());
|
||||
|
||||
try (HSSFWorkbook wb = new HSSFWorkbook(new ByteArrayInputStream(bos.toByteArray()))) {
|
||||
assertNull(wb.getEncryptionMode());
|
||||
wb.setEncryptionMode(null);
|
||||
assertEquals("Test", wb.getSheetAt(0).getRow(1).getCell(1).getStringCellValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue