CBFS Storage includes built-in support for powerful and secure symmetric encryption using 256-bit AES algorithm. Encryption can be applied to individual file (each file having its own encryption key), to the whole storage (encryption is applied to pages of the storage, rather than to file pages) or both.
However, there are certain scenarious such as PKI-based encryption or Digital Rights Management (discussed in the knowledgebase articles), which require more sophisticated security techniques. In this case you can use custom encryption.
Custom encryption is specified by setting encryption mode for the file or storage to ecCustom. In this mode CBFS Storage will fire various OnData* and OnHash* events (see the details below) which you must handle. The events are used to encrypt or decrypt the data, to calculate hash and to validate the existing hash (i.e. check if the data corresponds to the stored hash).
In APIs that have events (VCL, .NET, C++ class) the event handlers are set by assigning them to events, exposed by SolFSStorage class. Alternatively you can pass the event handlers as parameters to CreateOpenCB() constructor.
You can use any encryption algorithm that you need to encrypt the data. There exists one limitation though - encryption or decryption operation may adjust the size of the data block only within 32-byte boundary. This is fine for symmetric encryption algorithms, which perform only transformation of bytes (in ECB mode they may expand the block size to 16- or 32-byte boundary). However if you want to keep any additional information about the encrypted data, you would need to store this information somewhere else (for example, in file tags or alternate streams for files or in RootData for the storage itself).
Encryption and decryption events have Key parameter. This parameter is used to pass the password, set for the storage or the individual file, to the event handler. You can set the file password to be the actual key used for encryption (and you will receive this password via Key parameter in your encryption/decryption event handlers) or you can pass some key identifier there.
Passing the key identifier instead of the encryption key is used in the following cases:
Due to certain design specifics, encryption and decryption events don't include the name of the file being encrypted/decrypted. If you need the file names, you can take the following approach: pass the file name (or the hash of the file name or file ID) in the Key parameter together with the encryption key or key identifier.
Remember that encryption handler (especially in case of whole-storage encryption) is invoked really frequently so key lookup using the key identifier must be as fast as possible.
Hashes are used to determine correctness of the provided encryption key. If you use custom encryption, you must provide event handlers for hash calculation and validation. However you are not mandated to perform actual hashing operations. If you want to further strengthen security or you have other means for controlling correctness of the key, you can return some constant value as a result of hash calculation, and return True as a result of hash validation.
Here's the list of events that your application needs to handle: