Blowfish is symmetric block cipher encryption algorithm designed by the famous IT security technologist, BT Chief Security Technology Officer, and author Bruce ‘Almighty’ Schneier in 1993. The Blowfish encryption algorithm operates on 64-bit bit blocks of plaintext and supports variable key lengths ranging from 32 up to 448 bits; the default key length is 128 bits.
The technicalities of the Blowfish algorithm are quite complex and involve Feistel ciphers using large key-dependent S-boxes. As there is no successful cryptanalysis attacks known a Blowfish secured message can only be cracked using brute-force. This, in turn, can be prevented by using 256-bit keys for example.
Please find in Bright Hub’s article Can AES Encryption be Cracked? why attempts of cracking Blowfish used in conjunction with a reasonable lenght key by means of brute force can be ruled out (The underlying maths principles have been translated in easy-to-understand language).
The benefits of Blowfish include that the algorithm is unpatented and royalty-free, without any licensing requirements. The same is true for Twofish, an AES finalists designed by Schneier et al’s Counterpane Labs, gradually replacing Blowfish encryption. Twofish, first published in 1998, is a symmetric key block cipher algorithm using a block size of 128 bits .
Twofish uses key lengths of 128 bit, 192 bit or 256-bit. The Twofish algorithm is similar to the Blowfish algorithm and applies 16 rounds of encryption to 64-bit bit blocks plaintext input. More about block ciphers and stream ciphers can be found in Bright Hub’s article Types of Encryption.
Depending on on the key length as well as whether Twofish is used for hardware based or software based encryption Twofish may outperform AES in terms of speed. Many people believe Rijndael has just become more popular than Twofish because it received more attention since it was chosen for Advanced Encryption Standard (AES) by NIST in 2001.
When using the MSXML2 library, you typically load XML files from disk into a DOM (Document Object Model) object by creating an instance of IXMLDOMDocument and calling its load function—where you pass a BSTR representation of the file name. However, I had a situation recently where, due to security concerns, I needed to first decrypt the XML data in memory and then load that memory—without writing it to disk—into a DOM object. Surprisingly, I wasn’t able to find any open source examples of how to do this so I wrote a couple of helper functions to accomplish the task. Hopefully, these functions will help others that run into a similar situation.
Since Bruce Schneier introduced the Blowfish encryption algorithm in 1993, its had many implementations. I’ve personally found George Anescu’s work to be especially easy to use in scenarios where I’ve needed fast and reliable means of encrypting and decrypting data. Therefore, my functions work with data that is encrypted using his CBlowFish class.
The first thing I learned when searching for a solution is that the IXMLDOMDocument object supports a function called loadXML, which takes a BSTR value representing the XML to parse. Since I like to keep the client side as easy and clean as possible, I wanted the client to call a single function that would pretty much do everything. As a result, I created the DecryptFile2Bstr function, which takes an input file name and password (both char pointers) and returns a BSTR that can then be used with the IXMLDOMDocument::loadXML function:
BSTR DecryptFile2Bstr(char* inputFileName, char* password)
{
try
{
int requiredFileSize;
CBlowFish oBlowFish((unsigned char*)password, sizeof(password));
char *buffer = GetFormattedFileContent( inputFileName, requiredFileSize );
oBlowFish.Decrypt((unsigned char *)buffer, requiredFileSize);
return _com_util::ConvertStringToBSTR(buffer);
}
catch ( char *ex )
{
throw ex;
}
}
As you can see, the DecryptFile2Bstr function instantiates a CBlowFish object and then calls another helper function I wrote, GetFormattedFileContent, before invoking the CBlowFish::Decrypt function. As the data used by both the GetFormattedFileContent and CBlowFish::Decrypt functions is in the form of a char buffer, the DecryptFile2Bstr function calls the standard COM utility function ConvertStringToBSTR before returning to the caller.
The Blowfish algorithm is based on eight-byte blocks, so the GetFormattedFileContent function reads the data into memory accordingly. Note the padding at the end of the function to accommodate this rule:
char* GetFormattedFileContent(char *filePath, int &requiredFileSize)
{
FILE *fp = fopen(filePath, "r+b");
int fileSize = FileSize(fp);
int index = fileSize;
if ( (fileSize %
!= 0 )
requiredFileSize = ((fileSize /
+ 1) * 8;
else
requiredFileSize = fileSize;
char *buffer = new char[requiredFileSize + 1];
fread(buffer, sizeof(char), fileSize, fp);
buffer[fileSize] = 0;
fclose(fp);
while (index < requiredFileSize)
buffer[index++] = 0;
return buffer;
}
int FileSize(FILE *fp)
{
char buffer[1];
int count = 0;
fseek(fp, 0, SEEK_SET);
while (fread(buffer, sizeof(buffer), 1, fp) != 0) count++;
fseek(fp, 0, SEEK_SET);
return count;
}
Using the DecryptFile2Bstr Function
Assuming your data has been encrypted using the CBlowFish class, you can load it into an XML DOM object with two lines of code:
#import <msxml4.dll> named_guids
using namespace MSXML2;
...
::CoInitialize(NULL);
MSXML2::IXMLDOMDocumentPtr plDomDocument;
HRESULT hr = plDomDocument.CreateInstance(MSXML2::CLSID_DOMDocument);
if (SUCCEEDED(hr))
{
// load the file as an XML document
BSTR xmlfile = DecryptFile2Bstr(L"MyFile.xml", DEFS_ENC_PASSWORD);
variant_t vResult = plDomDocument->loadXML(xmlfile);
...
Looking Ahead
Combining the MSMXL2 IXMLDOMDocument::loadXML with my helper functions, I was able to read the client’s sensitive data into memory and decrypt it without first having to decrypt it to disk. I’ve also extended these functions to include other helper functions that perform such tasks as decrypting a file with CBlowFish-encrypted data to a specified file (DecryptFile2File) and encrypting plain ASCII data to a CBlowFish-encrypted file (EncryptFile2File). If you have any need or interest in these functions, email me and I’ll also post them for public use.