Encrypted Application File Format

Motivation

Suppose you're writing a plug-in for the next generation application which shall use an archive file format with a custom file suffix (extension) as a persistent container for some application data, e.g. a text document, and you need to make sure that nobody can read or modify the contents of the custom file format aside from authenticated parties.

Then, wouldn't it be nice if you wouldn't need to worry about how to read or write archive files using cumbersome archive type specific APIs? And wouldn't it be also nice if you wouldn't have to deal with complex encryption, decryption and authentication code? And wouldn't it be even nicer if you wouldn't have to write the user dialog for password prompting?

Accessing Encrypted and Authenticated Application File Formats

Thanks to the TrueZIP File* module, here's your relief: The TFile, TFileInputStream and TFileOutputStream classes can read and write entries within an encrypted and authenticated archive file as if they were plain files in regular directories in the file system.

First, you need to register your custom application file format suffix with an instance of an archive driver class like this:

TConfig.get().setArchiveDetector(
    new TArchiveDetector(
        "fox|bax",
        new SafeZipRaesDriver(  IOPoolLocator.SINGLETON,
                                KeyManagerLocator.SINGLETON)));

Once this has been called, any new TFile object will recognize the file suffixes fox and bax, whereby case is ignored, and assume the ZIP.RAES file format to read or write these files.

Note that TrueZIP automatically recognizes false positive archive files, so it cannot get confused by files with arbitrary content which accidently use the suffix of your custom application file format.

Please also note the usage of the class SafeZipRaesDriver for accessing the ZIP.RAES file format. This is one of two available archive driver implementations for TrueZIP's custom encrypted ZIP.RAES file format (or TZP for short). The other one is the class ParanoidZipRaesDriver. A TZP file is a ZIP file with UTF-8 encoded entry names (like the JAR file format) which is wrapped in a RAES file envelope. RAES is TrueZIP's custom Random Access Encryption Specification which supports SHA-256 authentication and AES-256 decryption in CTR block mode for transparent, read/write access to its encrypted payload. By using CTR mode, RAES supports transparent random read access to its encrypted payload, which makes reading a TZP file pretty fast.

Note the injection of the KeyManagerLocator.SINGLETON into the SafeZipRaesDriver. This object is responsible for resolving keys by prompting the user for passwords. It will check if the JVM is in headless mode and then use the console for prompting, otherwise a Swing GUI. If you want to hard code a password instead, you would need to inject an instance of your own implementation of the interface KeyManagerProvider. For more information, please refer to the article about Key Management.

Now you can easily create or overwrite an entry in your custom application file format like this:

OutputStream out = new TFileOutputStream("file.fox/contents.xml");
try {
    ...;
} finally {
    out.close(); // ALWAYS close the resource here!
}

Alternatively, you could use a TFileWriter.

This is how you could read the entry again:

InputStream in = new TFileInputStream("file.fox/contents.xml");
try {
    ...;
} finally {
    in.close(); // ALWAYS close the resource here!
}

Alternatively, you could use a TFileReader.

And finally, to delete a virtual directory tree - in this case your custom application file - you could use this:

new TFile("file.fox").rm_r();

Note that calling the method rm_r() is required to recursively delete the application file because the TFile object refers to a virtual directory, which cannot get deleted using similar methods like delete() or rm() unless it's empty.

Committing Changes / Cleaning Up

If your application has created or changed one or more archive files, then these changes need to get committed sometime. Even if your application has done read-only acess to the virtual file system, some temporary files may have been created to speed up random access - this dependends on the driver implementation.

If your application is only short-running, then there is actually nothing to do because the TrueZIP Kernel automatically registers and de-registers a JVM shutdown hook which will commit all changes when its run. Note that shutdown hooks are run even if the application terminates due to a Throwable.

However, if your application is long running or wants to handle any exceptions, then you may want to manually call this operation - here's how to do this:

TVFS.umount();

As a side effect, once this operation succeeded, third parties (e.g. other processes) can safely access the processed archive files until the next time your application starts to operate on them again.

Performance Considerations

Take care not to call TVFS.umount() in a loop which updates the same set of archive files because this would result in poor performance in the order of O(n*n) instead of just O(n), where n is the total number of archive entries.

For more information, please refer to the Javadoc for TVFS.umount().