Pure Programmer
Blue Matrix


Cluster Map

Project: XOR Cipher

[[XOR_cipher|XOR Cipher]] is a particular easy type of stream cipher to use in encrypting data. It is a form of symmetric encryption in that the same password is used for encryption and decryption.

Write a program that reads in a file and writes out an encrypted form of the file to another file. It turns out that because XOR is its own inverse, the same algorithm with the same password will decrypt the file so you only need to run the program again on the encrypted file to decrypt it.

To encrypt or decrypt the file simply read a character from a binary mode file, XOR it with the corresponding character in the password, then write the result out to a binary file. Once you have used all the characters in the password, start again at the beginning of the password.

The program should take three arguments on the command line: name of input file, name of output file, and the password to use.

For example. Suppose you had a cleartext file called cleartext.txt that contained the following paragraph.

Orson Welles (May 6, 1915 - October 10, 1985) was an American actor, director, screenwriter and producer who is remembered for his innovative work in radio, theatre and film.

Using the Linux hexdump command we can see the values of the bytes in the file in both hexadecimal notation and as characters on the right.

% hexdump -C cleartext.txt 00000000 4f 72 73 6f 6e 20 57 65 6c 6c 65 73 20 28 4d 61 |Orson Welles (Ma| 00000010 79 20 36 2c 20 31 39 31 35 20 2d 20 4f 63 74 6f |y 6, 1915 - Octo| 00000020 62 65 72 20 31 30 2c 20 31 39 38 35 29 20 77 61 |ber 10, 1985) wa| 00000030 73 20 61 6e 20 41 6d 65 72 69 63 61 6e 20 61 63 |s an American ac| 00000040 74 6f 72 2c 20 64 69 72 65 63 74 6f 72 2c 20 73 |tor, director, s| 00000050 63 72 65 65 6e 77 72 69 74 65 72 20 61 6e 64 20 |creenwriter and | 00000060 70 72 6f 64 75 63 65 72 20 77 68 6f 20 69 73 20 |producer who is | 00000070 72 65 6d 65 6d 62 65 72 65 64 20 66 6f 72 20 68 |remembered for h| 00000080 69 73 20 69 6e 6e 6f 76 61 74 69 76 65 20 77 6f |is innovative wo| 00000090 72 6b 20 69 6e 20 72 61 64 69 6f 2c 20 74 68 65 |rk in radio, the| 000000a0 61 74 72 65 20 61 6e 64 20 66 69 6c 6d 2e 0a |atre and film..|

After running our program to generate the ciphertext.bin file using the password ‘Rosebud’ we would see the following scrambled contents.

$ hexdump -C ciphertext.bin 00000000 1d 1d 00 0a 0c 55 33 37 03 1f 00 11 55 4c 1f 0e |.....U37....UL..| 00000010 0a 45 54 59 44 63 56 42 50 42 58 44 1d 0c 07 0a |.ETYDcVBPBXD....| 00000020 00 10 16 72 5e 43 49 42 44 5d 6a 5a 5a 45 15 14 |...r^CIBD]jZZE..| 00000030 17 72 0e 1d 45 23 18 01 20 06 10 04 0c 55 05 31 |.r..E#.. ....U.1| 00000040 1b 1c 17 4e 55 00 3b 1d 16 06 16 1a 16 7e 4f 00 |...NU.;......~O.| 00000050 06 10 10 01 3c 18 01 0c 16 10 16 72 0e 1d 01 42 |....<......r...B| 00000060 05 16 3d 0b 06 06 07 07 44 25 07 1c 45 0b 06 44 |..=.....D%..E..D| 00000070 20 0a 1e 00 0f 17 01 20 0a 17 45 04 1a 16 72 07 | ...... ..E...r.| 00000080 1a 16 42 1c 0a 3c 00 05 04 16 1c 12 37 4f 04 0a |..B..<......7O..| 00000090 10 1e 44 3b 01 53 17 03 11 0d 3d 43 53 11 0a 10 |..D;.S....=CS...| 000000a0 05 26 1d 16 45 03 1b 00 72 09 1a 09 0f 5b 6e |.&..E...r....[n|

Here are the commands to encrypt, decrypt and compare the final results:

$ ./XORChipher cleartext.txt ciphertext.bin Rosebud $ ./XORChipher ciphertext.bin cleartext_decrypt.txt Rosebud $ diff cleartext.txt cleartext_decrypt.txt

The diff command shouldn’t print any differences. On Windows use the “comp” command instead of “diff”.

Even though this can be a "perfect" encryption technique if the password is as long as the cleartext file, it doesn't always result in an unbreakable encryption. Why is this? What is the worst case?

Output
$ g++ -std=c++17 XORCipher.cpp -o XORCipher -lfmt $ ./XORCipher ../../data/text/GettysburgAddress.txt output/testGettysburgAddress.xor AbrahamLincoln $ g++ -std=c++17 XORCipher.cpp -o XORCipher -lfmt $ ./XORCipher output/testGettysburgAddress.xor output/testGettysburgAddress.xor.txt AbrahamLincoln $ diff ../../data/text/GettysburgAddress.txt output/testGettysburgAddress.xor.txt $ g++ -std=c++17 XORCipher.cpp -o XORCipher -lfmt $ ./XORCipher ../../data/text/UnicodeTest.utf8 output/testUnicodeTest.xor Unicode $ g++ -std=c++17 XORCipher.cpp -o XORCipher -lfmt $ ./XORCipher output/testUnicodeTest.xor output/testUnicodeTest.xor.utf8 Unicode $ diff ../../data/text/UnicodeTest.utf8 output/testUnicodeTest.xor.utf8

Solution