1. Technology

XOR in Encryption

No the most secure method of Enmcryption!

By

This is the eleventh tutorial in the series Online C Tutorial for beginners and is about using XOR for lightweight encryption and other uses.

The first tutorial in the series is the Online C Tutorial. The previous tutorial was about low level C functions.

This is a rewriting of the original C tutorials into single page bite size tutorials which can usually be run on either codepad.org or ideone.com.

What is XOR

This is a binary operation that exclusive ors every corresponding bit between two numbers. Here's a reminder of all three binary operations:

  • AND. A & B. If either A or B is 0 the result is 0.
  • OR. A | B.If either A or B is 1 the result is 1.
  • XOR. A ^ B.If A and B are different the result is 1, otherwise 0.

Don't confuse & with && or | with ||. When it's doubled up it's a logical operation not a binary one.

So this code:

if (a & b) {
.. Do Something
}

Will be called if the results of binary anding a and b is non zero. While this example:

if (a && b) {
.. Do Something
}

Will be called only if a is non zero and b is non zero. A very good example of that is this:

if (0xa & 0x5) {
  printf("Non zero");
}
Now try this:

if (0xa && 0x5) {
  printf("Non zero");
}

Anding the values 0xa and 0x5 with & gives 0. But 0xa && 0x5 is definitely non zero!

Example code to output decimal numbers in binary

This can convert int numbers that are up to 64 bits in size. It fills in the binary from right to left by looking at the right most binary digit (ie 1 or 0) and copies it in place. It then divides the number by 2 by using the >> operator until it's processed the number.

Finally it copies all of the binary digits to an output buffer and prints it. You can see this on ideone.com.

#include <stdio.h>

#define maxdigits 65
char buffer[maxdigits];

/* fill in from rhd */
void PrintBinary(int value) {
        char tempbuffer[maxdigits];
        char c;
        int index=maxdigits-2;
        tempbuffer[maxdigits-1]='\0';
        while (value >0) {
                tempbuffer[index--]= value & 1?'1':'0';
                value = value > > 1;
        }
        tempbuffer[index]='%';
        printf("%sb\n\r",&tempbuffer[index]) ;
}


int main(int argc, char* argv[])
{
        PrintBinary(10) ;
        PrintBinary(8) ;
        PrintBinary(32765) ;
        return 0;
}

Using the PrintBinary() function, this code below shows the three binary operations in action. You can see this on IDEONE.com.

int main(int argc, char* argv[])
{
 int a =0xcf;
 int b= 0xa5;
 int c;
 printf("This is a & b\n") ;
 printf(" a ") ;PrintBinary(a) ;
 printf(" b ") ;PrintBinary(b) ;
 c= a & b;
 printf(" ---------\n") ;
 printf("a&b ") ;PrintBinary(c) ;
 printf("\nThis is a | b\n") ;
 printf(" a ") ;PrintBinary(a) ;
 printf(" b ") ;PrintBinary(b) ;
 c= a | b;
 printf(" ---------\n") ;
 printf("a|b ") ;PrintBinary(c) ;
 printf("\nThis is a ^ b\n") ;
 printf(" a ") ;PrintBinary(a) ;
 printf(" b ") ;PrintBinary(b) ;
 c= a ^ b;
 printf(" ---------\n") ;
 printf("a^b ") ;PrintBinary(c) ;
 return 0;
}

Each hexadecimal digit is 4 bits. Digits 0-9 are the same as their decimal equivalents in binary (0000-1001) and hexadecimal digits A-F are represented by 1010 (A) through to 1111 (F). Every byte is represented by two hexadecimal digits, a 32 bit int by 8 hexadecimal digits. Here are some values, showing decimal, hexadecimal and binary.

  • 7, 0x7, 00000111246,0xd6, 11010110
  • 1050,0x41a 01000001101098765,0x181cd, 00010100000111001101

Flipping Bits

Another bit operator, most commonly seen in if statements is ~, known as the not operator, it actually flips every bit. It's the same as XOR with -1 but not quite as intuitive. These two statements do exactly the same.

c =~c;
c^=-1;

Use Binary Only when really necessary

Counting 1s and 0s in binary is error prone - quickly look at 1001101011. How big is that? Instead use decimal (base 10), or base 16 to specify numbers.

You can also use base 8 (Octal) in C by prefixing the number with a 0 So 023456 is an octal number = 10030 in decimal or 0x272E in hexadecimal. It's not that useful, about the only place you find it is in permissions in Linux file systems- 0644 or 0777 etc.

The magical property of Xor

If we xor two ints a and b to get c then a ^ c gives b and b ^ c gives a.

To create an encrypted text file, "binary xor" a file of text with a value, say 255 to get an encrypted file. If we xor this with 255, we get back our original unencrypted text. As encryption schemes go, this is light weight and probably the most reinvented wheel by novice programmers. It can be made tougher by using values to XOR that have at least 3 bits set instead of just 255.

In 8 bits, there are 256 different possible values- 0 to 255. There are only 36 values with 0,1, OR 2 set bits so that leaves 219 values which can be used. Stick these in an array and XOR the first byte of the file against the first byte of the table, 2nd against the 2nd array value and so on.

Although light weight it is useful for hiding text strings in applications. A binary file viewer/editor lets anyone look for text strings, hidden commands, registry keys, even secret passwords. By encrypting these it makes life a little harder for them.

The last example uses this technique in a simple example. The function hideandshow(char *,char *) processes the text in one buffer into another using 8 values for the xor. I picked 8 values from the output of example 3 with 5 or more bits set. With a higher number of bits set there is a greater overall transformation. Using only 8 values though means the range of transformations is lower.

As this is a light weight scheme, you should realize that it is not suitable for anything stronger than hiding text. Every developer thinks that their encryption scheme is uncrackable but that protection usually relies on hiding the method used to encrypt the data, this is known as "security through obscurity" and is not regarded every highly.

The strongest encryption schemes have their algorithms published and it is the strength of those algorithms that protects the data. If you write your own scheme, it is quite difficult to prevent your code being reverse engineered and if the prize is high enough, it will be.

The 8 values are indexed by the variable eindex which is repeatedly incremented but constrained within the range 0..7 by this line

eindex % = 8;

This uses the built in C modulus operator. As can be seen from the output, the text displayed by the last printf is identical to the text supplied to the first call of hideandshow() in the output listing below.

The hidden text is:

89
1a
e3
15
c8
93
cc
d0
b3
13
eb
57

The unhidden text is Hello world.

That concludes this tutorial.

  1. About.com
  2. Technology
  3. C / C++ / C#
  4. C Programming
  5. C Tutorials
  6. Online C Programming Tutorial for Beginners - Using XOR in Encryption

©2014 About.com. All rights reserved.