Security-Oriented C Tutorial 0xFC - A Simple XOR Encryptor
Welcome to a tutorial on XOR encryption. We'll be looking at what XOR is and how we can use it to encrypt or decrypt data.
XOR is a bitwise operation in which each of the bits are compared and applied with the XOR operation according to the following table:
We can see that it only results in a 1 if one of the inputs is a 1 and the other is a 0 and vice versa and because of this, it's hard to truly know which input bit was 1 and which was 0 if we look at it from the output. Let's do an example.
Take a character "A" and XOR it with the letter "B".
Here's how it works. "A" is 01000001 in binary and "B" is 01000010. To perform the XOR, we line up each of the bits and then use the table provided above.
The result is 00000011 which is 0x03.
How about XORing 0xEF with 0x11.
0xEF is 11101111 and 0x11 is 00010001 so that is:
The result is 0xFE. Simple!
One more just to make sure we understand the XOR completely. XOR the letter "B" with 0x03.
The result is "A". But hang on, this looks familiar. From our first example, we XORed "A" with "B" and obtained 0x03 but now we XORed "B" with 0x03 and that resulted in "A". Again, looking at the table, we see that if the inputs are 1 and 0 or vice versa, we always obtain the same result. This behavior allows the reverse XORing if we use the result with one of the original inputs letting us recover the other input.
We've defined an XOR_BYTE as 0xAA with the preprocessor directive #define. What this does is when our program is compiled, the compiler will replace every instance of XOR_BYTE in our code with its given value of 0xAA. Please pay attention to the syntax and know that there is no assignment operator (=) and no semicolon at the end of the line. Why do we do this? Well, it's sort of like a macro and it lets us change its value very easily without the need to manually go through our code and replacing it ourselves.
We make a function xorString to apply a byte-by-byte XOR operation to our string variable. Our first call to it will apply an encryption.
In the little blue box, the ^ operator represents the logical XOR operator. We use this to apply the XOR to each byte in our string with the XOR_BYTE value. We want to preserve the null terminating byte so that we can use printf to print it neatly instead of using a loop to iterate and print each value.
Our next call to xorString will decrypt the string according to the behavior of the XOR operation given that we use one of the original input values (XOR_BYTE).
Our encrypted string is in non-human readable and is displayed as such. Terminal cannot convert the text so it is seen as question marks. Our decrypted string has successfully been converted back into its original string as we expected.
To see the non-human readable text, we can direct our output into a file and then open it with Gedit.
Now that we know how to apply XOR to data, I want to give you guys a task to complete:
Write a piece of code which will allow you to encrypt a given file to produce an output file using the XOR operation I have just showed you. You must use argv to specify the input file and argv to specify the output file. You must also create a function xorFile which will perform the XOR operation on the files. Once you've made an attempt, try and test your program with an initial encrypt and then a second time to decrypt.
If you require a code skeleton, hop over to Pastebin.
XORing is a simple encryption method so do not rely on it to secure your data. It can be easily broken given a big enough sample size, especially if we are only using a single byte key.
In the next tutorial we will be using the function I assigned to you guys as a task to complete, giving it a bigger purpose. Until then!