VBfx / Common / Encryption

Introduction

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.

What Xor does

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.

Xor encryption

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?

Xor in VB

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.

RSA

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.

Extended Xor

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! :)

Important note

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.

Conclusion

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.

Navigation