How To: Security-Oriented C Tutorial 0xFC - A Simple XOR Encryptor

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.

What Is XOR?

XOR is a bitwise operation in which each of the bits are compared and applied with the XOR operation according to the following table:

Image via kkhsou.in

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.

Example Code

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).

Compiling and Running

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.

Homework

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[1] to specify the input file and argv[2] 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.

Conclusion

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!

dtm.

Just updated your iPhone to iOS 18? You'll find a ton of hot new features for some of your most-used Apple apps. Dive in and see for yourself:

8 Comments

Good article!. My 2 cents in case it may help

  • Instead of using just gcc and getting those ugly a.out., you can just type make xor. That will create an executable named xor (the source has to be in xor.c)
  • To look to the binary data, you can use hexdump -C or od -xc . or xxd. Like this: ./xor | xxd

Thanks for the share. I'm just trying to keep it simple.

Your tutorials are great, mahn. And you make it, really easy to understand some of this stuff. Thanks a lot

No problem, and thank you for following the series mate!

Love this series. Did the homework too. This whole series helps me even with my school and C++ in there. Keep it going.

-zem

Good job! As for C++, I'm sure Phoenix750 will be continuing his C++ series some time soon when he's not busy.

Can you describe what issues you're having? Also I'd suggest you use int ch instead of char ch because the EOF might not be registered correctly.

Share Your Thoughts

  • Hot
  • Latest