使用 Apache POI 进行二进制文件加密

Binary file encryption with Apache POI

我正在尝试使用 Apache POI 对二进制 xls 文件应用加密。 虽然我可以成功加密基于 xml 的文件,但如果我加密二进制文件,我将无法打开它,并且会收到错误的密码错误。

这是我的代码:

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

要加密 HSSF,您只需在写入 HSSFWorkbook.

之前执行 Biff8EncryptionKey.setCurrentUserPassword

最简单的例子是这样的:

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

这对我有用。如果我使用 Excel 打开 file.xls,它会要求我输入密码,如果我在那里输入 pass,工作簿就会打开。

如果目的是加密现有的未加密工作簿,那么这将是这样的:

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

同样的解决方案。在写 HSSFWorkbook.

之前简单地做 Biff8EncryptionKey.setCurrentUserPassword

此代码仅创建正确的加密工作簿供 Microsoft Excel 使用。 LibreOffice Calc 无法打开这些文件。所以似乎 LibreOffice Calc 所使用的加密方法是未知的。但是我还没有找到一种方法来更改 HSSF 的加密方法。所以 HSSF 加密似乎没有在 apache poi 中完全提供。 Apache POI - Encryption support 也没有显示示例。所以你可以打开和重写加密的HSSFWorkbook。如果 Biff8EncryptionKey.setCurrentUserPassword 未设置 null,则新的书面工作簿也会被加密。但是你不能从头开始写一个加密的HSSFWorkbook