Secure stream encryption -- guide/HowTo

This document describes secure stream encryption and its use (with the Cryptography API).

What is secure stream encryption?

Secure stream encryption provides subclasses of RReadStream, RWriteStream and CStreamStore that allow transparent access to encrypted streams and stores. It is implemented in terms of PBE (Password Based Encryption) -- that is, PBE does most of the work, the stream encryption classes are just wrappers that call PBE. The word "secure" refers to the fact that it uses well-known cryptographic algorithms.

What is secure stream encryption used for?

Secure stream encryption is used for example:

  • to password protect a database file

  • to store contacts encrypted on a mobile phone.

How do I use the secure stream encryption API?

Encrypting a stream

  • An encryption object (i.e., a CPBEncryptElement or CPBEncryptSet object) is necessary to allow the password based encryption of elements or multiple elements. Objects of this type contain the encryption key with its encryption data (i.e. password, cipher, salt, IV, iterations). Note that encryption objects can be recreated at a later stage from existing encryption data (see Storing encryption data)

  • An RWriteStream object (such as an RFileWriteStream, or RStoreWriteStream object) representing a target stream needs to be created in order to write the stream to a file or store

  • To support the encryption, an REncryptStream object is required, which forms an encryption filter or layer over the RWriteStream object.

  • Data can now be encrypted as it is externalized through the REncryptStream to the stream represented by the RWriteStream object.

Decrypting a stream

Reading from an encrypted stream is a similar process to that of writing to one.

  • An encryption object (i.e., a CPBEncryptElement or a CPBEncryptSet object) is needed to allow the password based decryption of elements or multiple elements.

  • An RReadStream object (such as an RFileReadStream, or RStoreReadStream object) needs to be created to read the stream from a file or store.

  • An RDecryptStream object is needed to form an encryption wrapper around the existing RReadStream object.

  • The encrypted data is internalized from the stream represented by the RReadStream object by way of the RDecryptStream object.

Handling multiple elements

CPBEncryptElement is good for handling individual elements, but for encrypting/decrypting information with multiple, independent elements it is advisable to use CPBEncryptSet; for instance, if you wished to store contacts encrypted on a mobile phone.

When you create a CPBEncryptSet object a master key is generated for you. This master key, which is encrypted with the password provided by the user of the class, enables the encryption/decryption of individual elements. The password may be changed by using the CPBEncryptSet::ChangePasswordL() function, which re-encrypts the master key with the new password.

Storing encryption data

In order to decrypt any information previously encrypted with a CPBEncryptElement or CPBEncryptSet object, you must store its encryption data along with it. Externalizing the CPBEncryptionData object will achieve this; for example:

writeStream << encryption->EncryptionData();

where writeStream is a RFileWriteStream object, and encryption is a CPBEncryptElement object. Failure to do this will result in the permanent loss of the encrypted information. See Secure stream example code.

Note

The Secure Store APIs REncryptStream and RDecryptStream currently support both the old CSecurityBase methods and the new PBE-based methods. In the near future, the old methods will be marked as officially deprecated.