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 extension (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 client API of the module TrueVFS Access, 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 extension with an instance of an archive driver class like this:
TConfig.current().setArchiveDetector( new TArchiveDetector("fox|bax", new SafeZipRaesDriver()));
Once this has been called, any new TFile object will recognize the file extensions fox and bax, whereby case is ignored, and assume the ZIP.RAES file format to read or write these files.
Note that TrueVFS automatically recognizes false positive archive files, so it cannot get confused by files with arbitrary content which accidently use the extension 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 TrueVFS'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 TrueVFS'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 that the SafeZipRaesDriver uses the TrueCommons KeyManager API for password management by default. You can configure key management by following the instructions on the page Key Management.
Now you can easily create or overwrite an entry in your custom application file format like this:
try (OutputStream out = new TFileOutputStream("file.fox/contents.xml")) { ...; }
Alternatively, you could use a TFileWriter.
This is how you could read the entry again:
try (InputStream in = new TFileInputStream("file.fox/contents.xml")) { ...; }
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 TrueVFS 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().