Many single file encryption algorithms use a simple stream cipher. These ciphers XOR the bytes in the file to be encrypted with a series of outputs from a pseudo-random number generator (PRNG). If the user encrypts the same file twice using the same key, the exact same encrypted output will be generated.
If a cryptanalyst thinks that a user has used the same key to encrypt two different files, he can XOR the two files together and cancel out the output from the PRNG. This leaves the cryptanalyst with a file that contains only the two original files XORed against each other. Guessing at the original contents becomes much easier in this case.
Additionally, the cryptanalyst can use plain text attacks. In these attacks, if the cryptanalyst knows the file type, then he can use knowledge of header formats to guess at the key stream used to encode the file.
The algorithm here uses the PRNG seeded with a high entropy source to insert a block of data at the beginning of the file. This data is the first data encrypted. On decryption, the first block of data is discarded, restoring the original file. Since the algorithm is designed so that single bit changes avalanche throughout the file, this initial block of data that is introduced makes the same file encrypt differently each time it is encrypted with the same key.
In Bruce Schneier's book "Applied Cryptography", he spoke of a block cipher where each block is XORed with the hash of the previous block's cipher text concatenated with the key.
A simple variation on this theme is to XOR the first block with the hash of the key and XOR subsequent blocks with the previous block's plain text and the hash used on the previous block.
Since the starting hash was generated from the key, the key still avalanches throughout the cipher text since each hash is used to generate the next block's hash.
Using the Code
The attached source code was developed to demonstrate the principal described above. It was developed using Visual C++ as a console application. All the code is in a single file; not very pretty but it works.
Points of Interest
On my 3GHz dual core Pentium, the code encrypts and decrypts at a rate of 8MB/s.
- 22nd July, 2008: Initial post