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
- know the key to get the source
- know the source to get the key
- 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…
private static string _b64 =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
private static int GetNFromB64(char n)
{
return _b64.IndexOf(n);
}
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.
private static string DecToBinary(int value, int length)
{
string binString = "";
while (value > 0)
{
binString += value % 2;
value /= 2;
}
string reverseString = "";
foreach (char c in binString)
reverseString = new string((char)c, 1) + reverseString;
binString = reverseString;
binString = new string((char)'0', length - binString.Length) + binString;
return binString;
}
private static int BinToDec(string Binary)
{
return Convert.ToInt32(Binary, 2);
}