I'm trying to apply encryption to a binary xls file with Apache POI. While I can successfully encrypt xml based files, if I encrypt a binary one I can't open it and I get the wrong password error.
This is my code:
@Test
public void testEncryption() throws Exception {
File file = new File("file.xls");
Workbook workbook = new HSSFWorkbook();
setData(workbook);
FileOutputStream fileOutputStream = new FileOutputStream(file);
workbook.write(fileOutputStream);
fileOutputStream.close();
encryptFile(file, "pass");
}
public void encryptFile(File file, String encryptKey) throws Exception {
FileInputStream fileInput = new FileInputStream(file.getPath());
BufferedInputStream bufferInput = new BufferedInputStream(fileInput);
POIFSFileSystem poiFileSystem = new POIFSFileSystem(bufferInput);
Biff8EncryptionKey.setCurrentUserPassword(encryptKey);
HSSFWorkbook workbook = new HSSFWorkbook(poiFileSystem, true);
FileOutputStream fileOut = new FileOutputStream(file.getPath());
workbook.writeProtectWorkbook(Biff8EncryptionKey.getCurrentUserPassword(), "");
workbook.write(fileOut);
bufferInput.close();
fileOut.close();
Biff8EncryptionKey.setCurrentUserPassword(null);
}
To encrypt HSSF
you simply do Biff8EncryptionKey.setCurrentUserPassword
before writing the HSSFWorkbook
.
Simplest example is as this:
import java.io.FileOutputStream;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
public class EncryptHSSF {
static void setData(HSSFWorkbook workbook) {
Sheet sheet = workbook.createSheet();
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue("Test");
}
public static void main(String[] args) throws Exception {
try (HSSFWorkbook workbook = new HSSFWorkbook();
FileOutputStream out = new FileOutputStream("file.xls") ) {
setData(workbook);
Biff8EncryptionKey.setCurrentUserPassword("pass");
workbook.write(out);
}
}
}
This works for me. If I open file.xls
using Excel
it asks me for password and if I type pass
there, the workbook opens.
If the aim is encrypting an existing unencrypted workbook, then this would be as so:
import java.io.FileOutputStream;
import java.io.FileInputStream;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
public class EncryptHSSFExistingFile {
public static void main(String[] args) throws Exception {
try (HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream("Unencrypted.xls"));
FileOutputStream out = new FileOutputStream("Encrypted.xls") ) {
Biff8EncryptionKey.setCurrentUserPassword("pass");
workbook.write(out);
}
}
}
So same solution. Simply do Biff8EncryptionKey.setCurrentUserPassword
before writing the HSSFWorkbook
.
This code only creates correct encrypted workbooks for usage with Microsoft Excel
. LibreOffice Calc
is not able to open those files. So seems encrypting method used is unknown for LibreOffice Calc
. But I have not found a way to change encrypting method for HSSF
. So HSSF
encryption seems not be fully provided in apache poi
. Apache POI - Encryption support also not shows an example. So you are able opening and rewriting encrypted HSSFWorkbook
. The new written workbook is encrypted too then if Biff8EncryptionKey.setCurrentUserPassword
is not set null
. But you cannot write an encrypted HSSFWorkbook
from scratch.