Reputation: 75
I'm trying to create an encrypted xlsx file using Apache POI. Here's my code, which runs just fine:
public static void Encrypt(String data) throws IOException, GeneralSecurityException, InvalidFormatException {
Workbook wb = new XSSFWorkbook();
Sheet sheet1 = wb.createSheet("sheet1");
sheet1.createRow(0).createCell(0).setCellValue(data);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
wb.write(bos);
bos.close();
POIFSFileSystem fs = new POIFSFileSystem();
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile, CipherAlgorithm.aes256, HashAlgorithm.sha512, 256, 16, ChainingMode.cbc);
Encryptor enc = info.getEncryptor();
enc.confirmPassword("pass");
OPCPackage opc = OPCPackage.open(new ByteArrayInputStream(bos.toByteArray()));
OutputStream os = enc.getDataStream(fs);
opc.save(os);
opc.close();
FileOutputStream fos = new FileOutputStream("provawrite.xlsx");
fs.writeFilesystem(fos);
fos.close();
}
The issue is when I open the generated file, excel keeps complaining that the file is corrupted.
I've also tried to change the EncryptionInfo
instantiation with different Encryption modes but nothing changes.
Can someone give me a hint?!?
Upvotes: 1
Views: 3710
Reputation: 61852
The encrypted output stream must be closed before writing out the file system. In your case it lacks os.close();
after opc.save(os);
.
But why the detour using ByteArrayOutputStream
at all?
Following works for me:
import java.io.*;
import org.apache.poi.poifs.filesystem.*;
import org.apache.poi.poifs.crypt.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class XSSFEncryption {
public static void doEncrypt(String data) throws Exception {
POIFSFileSystem fs = new POIFSFileSystem();
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
Encryptor enc = info.getEncryptor();
enc.confirmPassword("pass");
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("sheet1");
sheet.createRow(0).createCell(0).setCellValue(data);
// write the workbook into the encrypted OutputStream
OutputStream encos = enc.getDataStream(fs);
workbook.write(encos);
workbook.close();
encos.close(); // this is necessary before writing out the FileSystem
OutputStream os = new FileOutputStream("provawrite.xlsx");
fs.writeFilesystem(os);
os.close();
fs.close();
}
public static void main(String[] args) throws Exception {
doEncrypt("Test");
}
}
Upvotes: 8