1

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);
}
4

1 回答 1

1

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.

于 2021-03-14T07:45:05.330 回答