Search Apache POI

Apache POI - Encryption support

Overview

Apache POI contains support for reading few variants of encrypted office files:

  • XLS - RC4 Encryption
  • XML-based formats (XLSX, DOCX and etc) - AES and Agile Encryption

Some "write-protected" files are encrypted with build-in password, POI can read that files too.

XLS

When HSSF receive encrypted file, it tries to decode it with MSOffice build-in password. Use static method setCurrentUserPassword(String password) of org.apache.poi.hssf.record.crypto.Biff8EncryptionKey to set password. It sets thread local variable. Do not forget to reset it to null after text extraction.

XML-based formats - Decryption

XML-based formats are stored in OLE-package stream "EncryptedPackage". Use org.apache.poi.poifs.crypt.Decryptor to decode file:

EncryptionInfo info = new EncryptionInfo(filesystem);
Decryptor d = Decryptor.getInstance(info);

try {
    if (!d.verifyPassword(password)) {
        throw new RuntimeException("Unable to process: document is encrypted");
    }

    InputStream dataStream = d.getDataStream(filesystem);

    // parse dataStream

} catch (GeneralSecurityException ex) {
    throw new RuntimeException("Unable to process encrypted document", ex);
}
	

If you want to read file encrypted with build-in password, use Decryptor.DEFAULT_PASSWORD.

XML-based formats - Encryption

Encrypting a file is similar to the above decryption process. Basically you'll need to choose between standard and agile encryption. Apart of the CipherMode, the EncryptionInfo class provides further parameters to specify the cipher and hashing algorithm to be used.

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

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

OPCPackage opc = OPCPackage.open(new File("..."), PackageAccess.READ_WRITE);
OutputStream os = enc.getDataStream(fs);
opc.save(os);
opc.close();

FileOutputStream fos = new FileOutputStream("...");
fs.writeFilesystem(fos);
fos.close();     
     
by Maxim Valyanskiy