Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Implementing XOR cipher encryption / decryption in C#

0.00/5 (No votes)
18 Mar 2009 1  
A theoretical and practical implementation of the XOR encryption technology in C# which is extended from the Vernam cipher

Download Binary_XOREncryptionDecryption.zip - 5.01 KB

Download Project_XOREncryptionDecryption.zip - 16.35 KB

Implementing XOR cipher encryption / decryption in C#

A theoretical and practical implementation of the XOR encryption technology in C# which is extended from the Vernam cipher  

Introduction

XOFT is an encryption algorithm using a key to mash it up with the cipher string. Its result is base64 encoded. It’s surely not the most powerful encryption technology; however it’s sufficient if 100% security is not the primary goal.

The longer the key phrase, the harder it will take to crack the key. However, the longer the cipher text, the more easy it is to decode the string as repeating patterns in the encoded string are more easy to spot using frequency analysis.

The optimal solution is to have a key of the same length than the source string. This would create an uncrackable encryption not only in theory. That is only possible if the source string is always the same length (e.g. GUID’s). It’s not practical when ‘crypting plain text or text with variable length as the decoding side and the encoding side must have knowledge of the key.

Thoughts

One idea to extend the security factor is to create a dynamic key, related on the length of the source data.

The decoder would know the length of the source data as it’s always 2 times shorter than the base64 encoded result. (We make 8bit (octet) binary chunks, and split them up to 4bit (nybble) binary chunks.) As we do so, we create 2 characters out of one.

-> The decoder and encoder could use some internal algorithm to always create the same key based on the length of the cipher text.

To keep the encryption complex enough, the dynamic key is in theory an interesting idea but I won’t put this in place in this article.

How the data is encoded

I will reconstruct the encoding now in detail on a theoretical and practical basis – the decoding will work in the same way but upside down.

In our example, we will use 2 strings. One is the source (“hello world”) we would like to encrypt, and the other string is the key (“hidden”). Both the encoder and decoder must know about the key. 

• We will convert both the key and the source to a character array (ASCII)

• Each char of the source will be XOR’ed with each char of the key

• The result will be added by the length of the key (“hidden” has 6 chars)

• If the key is shorter than the source, it will be rotated

• Now we convert the resulting value into a octet binary value

• These binary strings will be joined and splitted up into nybbles

• The 4 bit junks are converted back into a decimal value

• Then we multiply each item in the decimal result array by 4 and add m=m0,m1,m2,m3

• Close to be finished, we now convert each decimal value into a bas64 value

Theoretical example of the encryption

To make things easy, let’s take a short source string and a short key.

Source = “hello world”
Key = “hidden” 

Split this up into characters:

Source:
h = 104
e = 101
l = 108
l = 108
o = 111
= 32
w = 119
o = 111
r = 114
l = 108
d = 100
 

Key:
h = 104
i = 105
d = 100
d = 100
e = 101
n = 110

Now we gonna XOR this up and add 4

We take the (source[n] ^ key[n1]) + 4 where n1 is a rotating value (n1 < key.Length < n1). This will mix the key into the source string. The only 3 methods to get them separated again is to

  1. know the key to get the source
  2. know the source to get the key
  3. use a brute force attack to get both of them


(104 ^ 104) + 6 = 6
(101 ^ 105) + 6 = 18
(108 ^ 100) + 6 = 14
(108 ^ 100) + 6 = 14
(111 ^ 101) + 6 = 16
(32 ^ 110) + 6 = 84
(119 ^ 104) + 6 = 37
(111 ^ 105) + 6 = 12
(114 ^ 100) + 6 = 28
(108 ^ 100) + 6 = 14
(100 ^ 101) + 6 = 7
 

Converting to binary 

After we have our source/key mash up we convert this to binary values:

6 = 00000110
18 = 00010010
14 = 00001110
14 = 00001110
16 = 00010000
84 = 01010100
37 = 00100101
12 = 00001100
28 = 00011100
14 = 00001110
7 = 00000111

Create the nibble junks and convert it to a base64 sequence

1st we need to convert the binary octet values into on big sequence (string). Then we split this string up into 4 character sequences which are our nybbles.

00000110000100100000111000001110000100000101
01000010010100001100000111000000111000000111


Splitting this up into nybbles looks like:

0000 0110 0001 0010 0000 1110 0000 1110 0001 0000 0101 
0100 0010 0101 0000 1100 0001 1100 0000 1110 0000 0111


And converted back into decimal values:

0 6 1 2 0 14 0 14 1 0 5 4 2 5 0 12 1 12 0 14 0 7 


Now we multiply each value with 4 and add m, where m is a sequence of 0,1,2,3

0*4+0, 6*4+1, 1*4+2, 2*4+3, 0*4+0, 14*4+1, 0*4+2, 14*4+3, 
1*4+0, 0*4+1, 5*4+2, 4*4+3, 2*4+0, 5*4+1, 0*4+2, 12*4+3, 
1*4+0, 12*4+1, 0*4+2, 14*4+3, 0*4+0, 7*4+1 


This will finally result in these values which get converted into base64:

0 25 6 11 0 57 2 59 4 1 22 19 8 21 2 51 4 49 2 59 0 29
A Z  G L  A 5  C 7  E B W  T  I V  C z  E x  C 7  A d

Output of the code

This is the base64 encoded string, which was made up from our source “hello world” and our key phrase “hidden”:

AZGLA5C7EBWTIVCzExC7Ad

Little helper

You may have noticed that we do some conversion from integer to base64 and back and from integer to binary and back. For most of this there is no native C# code (afaik) so here are the functions for converting these types. I found a lot of pretty complicated functions in the internet but I’m virtually certain that the following two functions are optimized enough.

Code for the base64 functionality

There might be better implementations, though…

// this is the base64 alphabet – depending on
// the standard that last characters (+/=) can vary
// possibile options are (-_%) (!*_) etc...

private static string _b64 =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

// expects a base64 character and returns it's position in the base64 alphabet
private static int GetNFromB64(char n)
{ 
    return _b64.IndexOf(n);
}
// expects a position in the base64
// alphabet and returns it's base64 character.
private static string GetB64FromN(int n)
{
    if (n > _b64.Length)
        return "=";

    return new string(_b64[n], 1);
}  


Code for binary functionalty

There might be better implementations, as well. I still wonder why .NET provides us with an option to convert binary strings to integers, but no simple way to convert integers to binary strings… I’m missing a good string.Reverse() function, though.

The DecToBinary is derived from several code snippets on the internet from multiple authors. So unfortunately I’m not able to give proper credits on this one.

// expects a integer value and length of the binary string (e.g. 4, 8, 16).
// returns the padded binary string
private static string DecToBinary(int value, int length) 
{ 
    // Declare a few variables we're going to need
    string binString = "";

    while (value > 0)
    {
        binString += value % 2;
        value /= 2;
    }

    // we need to reverse the binary string
    // that's why we are using this array stuff here.

        string reverseString = "";
    
    foreach (char c in binString)
        reverseString = new string((char)c, 1) + reverseString;
    
    binString = reverseString;

    // do the padding here
    binString = new string((char)'0', length - binString.Length) + binString;
    return binString;
}

// expects the binary string and returns it's integer equivalent
private static int BinToDec(string Binary)
{
    return Convert.ToInt32(Binary, 2);
}  

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here