Java 使用ApachePOI进行二进制文件加密

Java 使用ApachePOI进行二进制文件加密,java,apache-poi,poi-hssf,hssf,apache-poi-4,Java,Apache Poi,Poi Hssf,Hssf,Apache Poi 4,我正在尝试使用ApachePOI对二进制xls文件进行加密。 虽然我可以成功地加密基于xml的文件,但如果我加密了二进制文件,我就无法打开它,而且密码错误 这是我的代码: @Test public void testEncryption() throws Exception { File file = new File("file.xls"); Workbook workbook = new HSSFWorkbook(); setData(work

我正在尝试使用ApachePOI对二进制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
加密似乎没有在
apachepoi
中完全提供。也不显示示例。因此,您可以打开并重写加密的
HSSFWorkbook
。如果未设置
null
,则新编写的工作簿也会加密。但是您不能从头开始编写加密的
HSSF工作簿

您的代码与类似,但不完全匹配--可以尝试该示例吗?使用,您可以将HSSF工作簿的加密模式更改为binaryRC4,从而允许在LibreOffice中打开它。当然,首选的加密方式是XSSF工作簿上的敏捷加密。这将在即将发布的POI 5.0.1(或6.0.0)中提供,我不确定,但我认为ops问题是加密现有文件和保留旧记录的组合。因此,从头开始的解决方案可能不适用于这里。@kiwiwings:可能,但同样的解决方案是:在编写
HSSFWorkbook
之前,只需执行
Biff8EncryptionKey.setCurrentUserPassword
。我的问题是,我用LibreOffice打开它时出错了!谢谢,你的回复给了我一个确认,帮助我找到了答案problem@firegloves:你说得对。使用
LibreOffice Calc
时出现问题。请看我的补充。@AxelRichter:我对主干版本有一个未完成的修复。Libre Office失败的原因是,POI默认生成CryptoAPI加密信息,而LO似乎不支持该信息。可以强制使用binaryRC4,但写入文档属性时会失败。我将尝试以更好的方式重构和记录它。