Encryption can be important whatever project you're working on. Take a internet game for example, where everyone should be able to upload a score. Remember all the people out there trying to cheat and upload any highscore they want. If you just submit the data over a unsecure internet connection, many people will beat your code without any problems.
Before we start out with encryption we need some math. Remember that the function we'll use have to work in both directions: encode and decode. A very simple function that can achieve this is the binary Xor. I'll give you a short introduction to this binary operator now, for those who're already used to it please feel free to skip that part.
What Xor does is nothing special: Two different values become 1, two same values become 0. Here's all possibilities:
0 Xor 0 = 0 (same values)
0 Xor 1 = 1 (different values)
1 Xor 0 = 1 (different values)
1 Xor 1 = 0 (same values)
Now since this is a binary operation you get weird results when working with numbers. Here's a example:
10 Xor 40 = 34
Wonder how this comes? Let's see how the numbers show up as binaries:
10 = 001010 Xor
40 = 101000 = 34 = 100010
Now that you see the binary numbers everything should be clear. Note that the computer does not convert the numbers into binaries first - it always handles them as binaries :)
The interesting thing about this function is, that applying the function again will return the original number. This is shown in the following example. I took the numbers from before, except that the origin and result is swapped:
34 = 100010 Xor
40 = 101000 = 10 = 001010
This was the most important thing to remember: A Xor B = C and C Xor B = A again.
So how can we use this for encryption? I guess you know about the ASCII code, where all possible letters, numbers and special chars are encoded as numbers in the range 0 - 255 (that's 8 bit). The uppercase A for example is equal to 65, B = 66, C = 67, and so on. Now if we take a key number, say 12, and Xor it to 65 we get 77 (a uppercase M). Or other said: A Xor 12 = M.
And as we've seen before we can just Xor the result with 12 again to get back the original number. So M Xor 12 = A.
The string FOX Xored with 12 would return: JCT - as you can see this is a quite simple encryption (ABC Xor 12 = MNO) but for being only one simple operation it's fairly good, huh?
In VB we have to do 3 steps to encode a string:
To keep things simple I'll just show you the code to convert a string to ASCII codes and back. The function will store the codes in a byte array so we can easily handle the array later:
Public Function StringToArray( iText as String, iArray() as Byte ) as Long Dim Size as Long Dim Length as Long 'Get size Size = LenB( iText ) Length = ( Size / 2 ) - 1 If Size > 0 Then 'Allocate memory ReDim iArray( Length ) 'Fill array CopyMemory iArray( 0 ), ByVal StrPtr( StrConv( iText, vbFromUnicode ) ), ( Length + 1 ) End If 'Return count StringToArray = Length End Function
As mentioned before the computer handles all values as binaries, no matter if it's a number or a character. That's why we can just CopyMemory the string into a byte array. But oh well, VB works with UNICODE strings instead of ASCII, that's why we have to convert the string first. However, you don't have to understand the code, you can use it as-is in your projects.
Converting back the byte array to a string is faily simple, VB lets us apply a byte array to a string without any problems. Just note that we still have to convert the string back to UNICODE:
Public Function ArrayToString( iArray() as Byte ) as String 'Return string ArrayToString = StrConv( iArray, vbUnicode ) End Function
Now that we've got a byte array the rest becomes quite simple. We can just step through the array and Xor each value with a key and get back the encoded char code:
Dim A as Long Dim Key as Byte Dim Temp() as Byte 'Encode a string StringToArray "test", Temp 'Xor array Key = 55 For A = 0 To UBound( Temp ) Temp( A ) = Temp( A ) Xor Key Next 'Show result MsgBox ArrayToString( Temp ) 'Will show "CRDC"
If you understood this feel free to play around with it - congratulations to your first encryption. In the next part I'll show you how to develop a more secure encoding. However we'll continue using Xor in this tutorial - that's a fast and nice way but you'll never reach the point where your code is unbeatable. Just because people can still do a little reverse engineering and extract your code.
Other codes, like the famous RSA, work completely different - everyone knows exactly what it does but still no one can break the encryption. That's because our computers are still too slow to solve a mathematical problem (within a useful time) which is the core idea of RSA: Factorization.
You know, 24 => 2*2*2*3 and such. The factors you get are always prime numbers and that's exactly the point. Let's take two prime numbers: 7 and 23. If you multiply those you get 161 and the only way to factorize 161 is 7 * 23. Quite simple huh? Now for small numbers this works fine but in case or RSA the prime numbers we take are 1024 bits and that's really a big number (around 308 digits). However, multiplying two big numbers is still very easy but factorizing such a large number takes up years. That's why RSA is quite secure.
Coming back to our little encryption routine. As you've seen Xor works quite simple - basically it's nothing more than some kind of addition. Remember that ABC Xor 12 = MNO and even worse: AAAA Xor 12 = MMMM! That's a pattern we have to destroy, because patterns always help cracking a code.
The only way to get irregulary results is changing the key while encoding. Note that it does not matter what happens to the key, as long as you can re-construct the changes when decoding. For example we could just add some value to the key within the loop:
'Xor array including A For A = 0 To UBound( Temp ) 'Modify key Key = ( Key + A ) Mod 256 'Encode char Temp( A ) = Temp( A ) Xor Key Next
In case you wonder why we need the "Mod 256" here: The key must stay in the range 0 - 255. If it was bigger the encryption would fail because 8-bit ASCII is limited to this range. Just leave it there and don't care about it.
If we now encode AAAA with 12 we get MMLN now which is a step into the right direction. Feel free to add any mathematical operation instead of (Key + A) to get better results! The following line shows you another nice example how to do this:
'Modify key Key = (Key + (Key / (A + 1)) * (A + Key) + A) Mod 256
Feel free to try this one out! :)
You can't just encode a text and send the result by mail, because it could contain invalid ASCII chars like 46, 8 or even 0 which means delete, backspace and end of text.
Of course this problem doesn't appear as long as you only encode files or byte arrays that are kept in memory - you just can't display the encoded text. If you need to show the encoded string, try to convert all characters to valid ASCII codes (numbers and letters).
Another nice solution to get around this problem is not to convert the byte array back to ASCII but convert them to hex codes (00 - FF) instead. This will double the text length (two hex digits for each character) but you won't have any problems.
Encryption is needed wherever you need to keep data secret and un-editable. Xor is a nice and easy way to achieve a fast encryption within a single loop and you can use the same function to encode and even decode a text. This will suffice for savegames or level passwords so the user can't just read your files in Notepad. However, if the user can do a reverse engineering (that's whenever he gets your program) the code is no longer secure.