Tibu Tibu - 22 days ago 9
Apache Configuration Question

Setting Password Protection on XSSF Workbook

I would like to add password protection to a xlsx file created with poi 3.14.
The documentation claims, that this is possible:

http://poi.apache.org/encryption.html

Using the example I tried it like this:

public static void main(String[] args)
{
try(Workbook wb = new XSSFWorkbook())
{

//<...>
try(ByteArrayOutputStream baos = new ByteArrayOutputStream())
{
wb.write(baos);
byte[] res = baos.toByteArray();
try(ByteArrayInputStream bais = new ByteArrayInputStream(res))
{
try(POIFSFileSystem fileSystem = new POIFSFileSystem(bais);) // Exception happens here
{
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
Encryptor enc = info.getEncryptor();
enc.confirmPassword("pass");
OutputStream encryptedDS = enc.getDataStream(fileSystem);
OPCPackage opc = OPCPackage.open(new File("example.xlsx"), PackageAccess.READ_WRITE);
opc.save(encryptedDS);
opc.close();
}
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}


Unfortunately, the code in the example is not compatible to XLSX files and as a result I receive the following exception:

The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)


Can anybody help please? I am unable to find the correct alternative for XLSX...

Thank you all for you help. Here is my working result:

public static void main(String[] args)
{
try(Workbook wb = new XSSFWorkbook())
{
Sheet sheet = wb.createSheet();
Row r = sheet.createRow(0);
Cell cell = r.createCell(0);
cell.setCellType(Cell.CELL_TYPE_STRING);
cell.setCellValue("Test");
try(POIFSFileSystem fileSystem = new POIFSFileSystem();)
{
EncryptionInfo info = new EncryptionInfo(EncryptionMode.standard);
Encryptor enc = info.getEncryptor();
enc.confirmPassword("pass");
OutputStream encryptedDS = enc.getDataStream(fileSystem);
wb.write(encryptedDS);
FileOutputStream fos = new FileOutputStream("C:/example.xlsx");
fileSystem.writeFilesystem(fos);
fos.close();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}

Answer

You've mis-read the documentation on encrypting in OOXML file. You're therefore incorrectly trying to load your file using the wrong code, when you just need to save it

Without any error handling, your code basically wants to be

// Prepare
POIFSFileSystem fs = new POIFSFileSystem();
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
CipherAlgorithm.aes192, HashAlgorithm.sha384, -1, -1, null);

Encryptor enc = info.getEncryptor();
enc.confirmPassword("foobaa");

// Create the normal workbook
Workbook wb = new XSSFWorkbook();
Sheet s = wb.createSheet();
// TODO Populate

// Encrypt
OutputStream os = enc.getDataStream(fs);
wb.save(os);
opc.close();

// Save
FileOutputStream fos = new FileOutputStream("protected.xlsx");
fs.writeFilesystem(fos);
fos.close();  
Comments