Objective Toolkit : Chapter 16 Utility Classes : Encrypted File I/O
Encrypted File I/O
Objective Toolkit provides a class to support encryption and decryption services for data written to and from a file.
Objective Toolkit provides the following modes:
Electronic Codebook (ECB)
Output Feedback Mode (OFB)— also known as Cipher Feedback (CFB).
The following sections describe the features and limitations of this encryption capability.
Electronic Codebook (ECB)
Electronic Codebook is moderately secure and allows random access reads and writes. The application of sophisticated cryptographic methods allows easier recovery of the contents of each of two or more files encrypted with the same password. Encourage your users to change their passwords frequently or implement another layer of key management.
Output Feedback Mode (OFB)
Output Feedback is more secure than ECB, but file access is unidirectional and sequential only. Therefore, an SECCryptoFile secured with OFB may be opened in either CFile::modeRead or CFile::modeWrite modes, but not both. Seek functions are not available in Output Feedback mode.
The SECCryptoFile Classes
Objective Toolkit provides file encryption services through the SECCryptoFile class and its helper SECBlackBox.
Figure 134 – The Objective Toolkit Encryption Class Hierarchy
SECCryptoFile
SECCryptoFile, a CFile derivative, provides encryption and decryption for data written to and read from a file. You need to assign a password to your user and he, in turn, must choose an encryption method. The encryption algorithms are described in detail in the following sections.
NOTE >> This class provides only medium-grade encryption. In other words, it is only intended to stop novice to intermediate hackers from accessing your data. If you require higher levels of security, patent and export laws come into play.
SECBlackBox
The SECBlackBox class is a helper class that encapsulates the encryption algorithm itself.
The Encryption Algorithm
The algorithm involves two or three phases:
Password transformation,
Stream cipher, and
Output Feedback (OFB mode only).
First, SECBlackBox transforms or hashes the password you selected into an array of 72 seemingly random characters that bear no resemblance to the original password. Then SECBlackBox uses this 72-byte passphrase to generate three keys – 23, 24, and 25 bytes in length.
During read or write operations, the SECBlackBox class subjects the data stream to what is known as a triple-key Vigenere cipher. The Vigenere cipher is called a symmetrical cipher, because you can use the same algorithm and key to encrypt and to decrypt.
Password Transformation
The password provided by the user is subjected to a hashing function to transform it into a 72-byte apparently scrambled character string, regardless of its initial size. The hashing function is as follows:
 
void SECBlackBox::HashString( char *from, int fromSize,
char *to, int toSize )
{
unsigned char p=0;
for (int i = 0;i < toSize;i++)
{
p += ( 17 * ( from[i%fromSize] + i ) );
to[i] = (from[i%fromSize] * p ) + from[(i+1)%fromSize];
}
}
In the preceding function, the string in from, fromSize characters long, is hashed into a buffer at to, toSize bytes long.
The Stream Cipher
The SECBlackBox uses a triple-ranked Vigenere cipher. In this implementation, the circular buffer or mask consists of three separate submasks that are combined to produce a final mask value with which the plain text is enciphered. In other words, given buffers B1, B2, and B3, with lengths l1, l2, and l3, respectively, the mask value M[i] for the ith character of the message would be:
 
M[i] = B1[i%l1]^B2[i%l2]^B3[i%l3];
The three buffers are filled as follows: the 72-byte hashed key is split into three subkeys – 23, 24, and 25 bytes long. Each key is loaded into a circular buffer, an instance of the class CCryptoRotor. Each rotor is then set with position zero selected. To encrypt (or decrypt at the lowest, or Vigenere level, this is a symmetrical cipher) a character, the mask character for each byte of the plaintext is generated as above. The mask character used to encrypt/decrypt the next character of plaintext, and then each rotor is advanced one position (the pointer is incremented and wrapped, if necessary). The rotor sizes are relatively prime, so the three wheels do not align the same way (and produce the same mask key) until 23 x 24 x 25 encryptions or decryptions have been performed. So, the effective key length is 13,800 bytes.
The Cipher Modes
The stream cipher operates in either electronic codebook mode (ECB) or output feedback mode (OFB). Output feedback mode is also known as cipher feedback mode (CFB).
ECB mode is the simplest and each character is treated independently. It is potentially less secure, but more tolerant of media errors in the file. You can use ECB to access data randomly. After the first XORing stage, the ciphertext byte is output, and the next plaintext byte is read. Because no information is carried from one byte to the next, any (1 byte) error in the stored file results in only one character being decrypted incorrectly.
Figure 135 – Electronic Codebook (ECB) Ciphering Topology
OFB adds an additional XOR to the three-step key XORing. The last character encrypted becomes part of the key for the next character. This has the effect of making the keystream at any point dependent on the message that preceded it. OFB is more secure than ECB, but if any errors are introduced into the encrypted file by an attacker or media failure, the remainder of the file becomes corrupted. This technique makes the cipher harder to crack, but as soon as a byte is read in incorrectly, the remainder of the message becomes indecipherable. Additionally, the sequential nature of the cipher limits the use to sequential access to a file. To this end, the seek-related functions are disabled in OFB mode, and they fire an ASSERT when used.
Figure 136 – Cipher Feedback (OFB) Ciphering Topology
Limitations
Most stream ciphers, particularly the Vigenere cipher, are technically less secure. The triple-ranked Vigenere cipher in ECB mode is harder to break than a short single-rank Vigenere. The triple-ranked Vigenere in OFB mode is more secure than an ECB mode cipher. Be aware, though, that this algorithm does not provide a great deal of security against governments and well-funded or highly skilled cryptographers.
Decryption of data files is easier for the sophisticated attacker if he or she is given two or more different files encrypted with the same key or password. However, this advantage is diminished greatly if the files are encrypted using OFB mode. This weakness might become apparent to a sophisticated attacker, but it will probably elude the average hacker.
Using SECCryptoFile
An SECCryptoFile is used almost the same way as a CFile is used, with a few exceptions. For example, you can open an SECCryptoFile without a password.
You can open an SECCryptoFile in either ECB or OFB modes. This is specified in the eModeCipherMode argument. If the SECCryptoFile is opened in OFB mode, it cannot be opened for random access or for Read and Write capability at the same time. An ASSERT fires if this mistake is made. To open a file called SECRET.DAT in read mode with cipher feedback and with password ABRACADABRA, you would create your CFile as shown in the following examples.
To encrypt data to a file
1. Instantiate an SECCryptoFile object. For example:
 
SECCryptoFile fEncrypted;
2. Open the file for writing using the Open() method, supplying a password and encryption mode. For example:
 
fEncrypted.Open(“secret.dat”, “abracadabra”, Cfile::modeRead, SECCryptoFile::OFB);
3. Call the Write() or WriteHuge() methods to write data to the file.
 
FEncrypted.WriteHuge(pBuffer, nCount);
NOTE >> CFile::modeReadWrite and the Seek methods are only available in ECB mode.
To read an encrypted file
1. Instantiate an SECCryptoFile object. For example:
 
SECCryptoFile fEncrypted;
2. Open the file for writing using the Open() method, supplying a password and encryption mode.
 
fEncrypted.Open(“secret.dat”, “abracadabra”, Cfile::modeWrite, SECCryptoFile::OFB);
3. Call the Read() or ReadHuge() methods to read data from the file.
 
NBytesRead = FEncrypted.ReadHuge(pBuffer, nCount);
NOTE >> CFile::modeReadWrite and the Seek methods are only available in ECB mode.
SECCryptoFile Sample
See the Objective Toolkit CFiles sample (Samples\Toolkit\MFC\Utility\CFiles) for an example of how to use SECCryptoFile. This sample does not ship with the product. For information on how to obtain this sample, see “Location of Sample Code” in the Getting Started part.