MynahSA provides input and output streams that are encrypted using OpenSSL's implementation of Counterpane's Blowfish cipher. Using the Mynahsa::IBlowfishStream and MynahSA::OBlowfishStream classes data can be encrypted on disk files or std::streams.
Strong encryption is particularly helpful for applications where your data needs to be secure - this mechanism enforces security because data cannot be read or written without encryption.
Unlike simple password protections that prevent a file from being loaded, files stored with the Blowfish stream are completely encrypted. Barring an attack on Blowfish or knowing the password it is extremely unlikely that the data will be extracted from an encrypted file.
The Blowfish streams are used similarly to the standard input/output streams presented in Tutorial 1: Simple Object Persistence, however, a password must be supplied to the class constructor.
To demonstrate the use of the Blowfish streams, a simple C++ struct will be archived. Three steps will be performed:
-
Step 1: Create an OBlowfishStream and archive the data.
-
Step 2: Display the contents of the archived data.
-
Step 3: Create an IBlowfishStream and restore data structure.
The data structure definition is the following: struct SimpleContainer {
void serialize(Archive& ar) {
ar & _name;
ar & _age;
}
string _name;
int _age;
};
The first step is to create an instance of the SimpleContainer and fill it with some data, then store it onto an output Blowfish stream using the password "Private Key". ostringstream ostr;
{
SimpleContainer sc;
sc._name = "Brett";
sc._age = 32;
OBlowfishStream obfs(ostr, "Private Key");
OArchive<OBlowfishStream> oabfs(obfs);
oabfs << sc;
}
To examine the data on the stream each character is displayed it as an integer; preventing control characters from affecting the console. for (unsigned int i=0; i<ostr.str().size(); i++) {
unsigned char ch = ostr.str()[i];
cout << "Stream[" << i << "] contains value: " << ((unsigned int) ch)
<< endl;
}
cout << endl;
This produces the output: Stream[0] contains value: 203
Stream[1] contains value: 41
Stream[2] contains value: 151
Stream[3] contains value: 189
Stream[4] contains value: 126
Stream[5] contains value: 126
Stream[6] contains value: 5
Stream[7] contains value: 196
Stream[8] contains value: 1
Stream[9] contains value: 25
Stream[10] contains value: 102
Stream[11] contains value: 51
Stream[12] contains value: 198
Stream[13] contains value: 26
Stream[14] contains value: 149
Stream[15] contains value: 212
These numbers are garbled and exactly what is expected from an encryption routine.
To decrypt and restore the object state the exact opposite process is performed: {
SimpleContainer sc;
istringstream istr(ostr.str());
IBlowfishStream ibfs(istr, "Private Key");
IArchive<IBlowfishStream> iabfs(ibfs);
iabfs >> sc;
cout << "sc's name: " << sc._name << endl;
cout << "sc's age: " << sc._age << endl;
}
Which produces the expected results: sc's name: Brett
sc's age: 32
-
The current implementation of IBlowfishStream does no checking of the validity of passwords. Because Blowfish will happily decrypt gibberish, attempting to recover a stream with an incorrect password is considered an error, and the results are unlikely to be correct. A future version of MynahSA will address this issue.
-
Stream closing: OBlowfishStream is a buffering stream that collects chunks of 8 bytes at a time. After eight bytes are accumulated they are encrypted and written onto the output stream. If your data is less then 8 bytes, be sure to close the stream prior to examining the data on the stream. OBlowfishStream's destructor automatically closes the stream.
-
Key strength is a function of its length. Please see OpenSSL's Blowfish notes for details.