Site hosted by Angelfire.com: Build your free website today!

Making Encrypt/Decrypt Work
Home Up High Level Design Layout of Controls Encrypt Decrypt Making Encrypt/Decrypt Work Using the Application

 

In the previous two documents, All About Our Encryption Algorithm and All About Our Decryption Algorithm, we learned about the algorithm we use to encrypt and decrypt text.  However, in real life there are often complications caused by limitations in the tools available.  Our project is no exception.

In order to make our application simple, we will be using common components to display the text and common streams to read and write the text to and from a file.  Since I've decided to stick to "character" streams, some constraints are placed upon us.  For example, some characters cannot be written or read from a "character" stream.  Since we do not know, ahead of time, what characters will be created by the encryption algorithm, we must assume that some of them cannot be written to a character without problems.  As well, we must assume that some cannot be read from a character stream without problems.

Additionally, the text box control that we will use to display text expects characters within a certain limit (specifically, the characters found in a text file).  We need to make sure that we never try to display characters that text box cannot handle.  Likewise, we need to make sure that we do not read or write characters to a character stream that a character stream cannot handle.

All of this is easy to address if we make some design decisions now.

We will make sure that all characters, when encrypted, result in characters that are within the normal range of readable and writable characters.  We will do this by adding an additional layer to our encryption algorithm and an additional layer to our decryption algorithm.

Encryption

The Concept

For encryption, rather than storing the result of a character encryption as a single character, we will translate the result into a string of digits representing, in decimal, the character code encrypted character.

For example, in the document All About Our Encryption Algorithm, we showed that if one encrypts the character 'W' by XOR'ing it with "X", we get the binary number 00001111 as a result.

That is, 'X' XOR 'W' = 01011000 XOR 01010111 = 00001111

Now, we never see the binary number directly.  From our point of view, a number is a number.  While the number is encoded internally as 00001111, if we were to translate it to a string using CStr, CStr would return the string "15", which is decimal for 00001111.  Thus, we would encrypt 'W' using the key 'X' as the string "15".

In order to distinguish were one encoded character, represented by a string of digits, begins and ends, we will separate them with a space character.  Thus, given some input text, the encrypted text will be a sequence of decimal integers, each corresponding to an encrypted character of the original text, separated by spaces.

For example, if we were to encrypt the text "ANT" using the key "XYZ", the encrypted text would be "25 23 14", where "25" represents the encrypted value of "A", "23" represents the encrypted value of "N" and "14" represents the encrypted value of "T".

Written mathematically:

'X' XOR 'A' = 1011000 XOR 1000001 = 11001 = 25 (base 10)

CStr(25) = "25"

Our editor will need to be able to distinguish between encrypted text and clear text (clear text is non-encrypted text (or decrypted text)).  We will adopt the following convention.

All encrypted text will start with the character sequence "#BEGIN ENCRYPTED " and end with the character sequence "#END ENCRYPTED".  The double quotes are not included in the character sequence.  The last character in "#BEGIN ENCRYPTED " is a space.  The last character in "#END ENCRYPTED" is the letter 'D' (We add a space to the end of "#BEGIN ENCRYPTED " because we wish to separate it, using a space, from the first encrypted character code in the text.  We do not add a space before "#END ENCRYPTED" because our algorithm (specified in pseudo code below) will place a space after each encrypted character, thereby leaving one before "#END ENCRYPTED".).

Therefore, using the example above, if we were to encode the text "ANT" using the key "XYZ", the encrypted text would be: "#BEGIN ENCRYPTED 25 23 14 #END ENCRYPTED"

Pseudo Code

While reading the following, keep in mind that in the encryption code, we are converting directly from a clear text string to an encrypted string.  String indices begin at 1.  Therefore, the first index of a string is 1 and the last is the length of the string.  This effects some of our calculations below.

Let DocumentText be a string of characters.  This string of characters represents the contents of the document.

Let Key be a string of characters.  This string of characters represents the secret key used to encrypt and decrypt the document.

Let EncryptedText be a string of characters initialized to "#BEGIN ENCRYPTED ".

Let TextLength be the number of characters in DocumentText.

Let KeyLength be the number of characters in Key.

Let Index be an integer, currently uninitialized, that will be used as a counter in our code.

For each integer between 1 and TextLength, starting with 1 and ending with TextLength, let Index be the aforementioned integer and do the following:

  1. Let DocumentCharacter be the character in DocumentText at Index.
  2. Let DocumentCharacterCode be the numeric value representing DocumentCharacter.
  3. Let KeyIndex be 1 + the remainder from the integer division of Index - 1 and KeyLength (note, this value will circle from 1 to the length of the key and back again, over and over).
  4. Let KeyCharacter be the character in Key at KeyIndex.
  5. Let KeyCharacterCode be the numeric value representing KeyCharacter (use Convert.ToInt to do the conversion).
  6. Let EncryptedCharacterCode be DocumentCharacterCode XOR KeyCharacterCode.
  7. Let EncryptedCharacter be the character represented by EncryptedCharacterCode.
  8. Append to the end of EncryptedText the character EncryptedCharacter and a space character.

Append to the end of EncryptedText with "#END ENCRYPTED"

Return EncryptedText

Decryption

The Concept

When we decrypt encrypted text, we transform the encrypted text back to clear text.  Stated in other words, we reverse the encryption process.

The first step in revering our encryption process is to remove the characters "#BEGIN ENCRYPTED " from the start of the encrypted text and remove the characters "#END ENCRYPTED" from the end of the encrypted text.

After we remove "#BEGIN ENCRYPTED " and "#END ENCRYPTED", what we have left is a sequence character codes expressed in decimal.  For example, given "#BEGIN ENCRYPTED 25 23 14 #END ENCRYPTED" we now have "25 23 14 ".

The next step is to transform string " 25 23 14 " to the array {"25", "23", "14"}.  We can perform this task using Visual Basic's Split function.

To decrypt the text, we translate each of the character codes, expressed now as a string, to integers.  Each of these integers is represented internally as a binary number.  Since they are binary numbers, we can perform the XOR operation on them.

For each element in the array mentioned above, convert it to an integer using CInt and then XOR the integer with the character code of the corresponding key character.  The result will be the character code of the decrypted character.  We then translate this character code to a character and append it to the end of a string.  At the end, the string contains the original clear text.

Let's take a closer look.

The string "#BEGIN ENCRYPTED 25 23 14 #END ENCRYPTED" is stripped of "#BEGIN ENCRYPTED " and "#END ENCRYPTED" resulting in " 25 23 14 ".

We next translate the string " 25 23 14 " to the array {" 25", " 23", " 14"} using Split.

Next, for each element in the array, we translate it into its integer value using CInt and then XOR it with the character code of the corresponding character in the key.  For example, if our key is "XYZ" then the character codes, in base 10, are 88, 89 and 90.

Retrieving the original text, therefore, requires doing the following:

Encrypted Character Key Code from Key Character Encrypted Character XOR Key Code from Key Character (this is the decrypted code). Character Corresponding to the Decrypted Code
25 88 65 A
23 89 78 N
14 90 84 T

Pseudo Code

While reading the following, keep in mind that in the encryption code, we are converting indirectly from an encrypted string to a decrypted string.  The conversion is indirect because we convert first, from a string to an array and then from an array to a string.  String indices begin at 1.  Array indices begin at 0.  Therefore, the first index of a string is 1 and the last is the length of the string.  The first index of an array is 0 and the last index is length - 1.  This effects some of our calculations below. 

Let EncryptedText be a string representing an encrypted document (see above for a description of what this looks like).  This is the text between "#BEGIN ENCRYPTED " and  "#END ENCRYPTED".

Let EncyptedTextArray be an array of strings.  It will be used to store the results of breaking up EncryptedText into an array of strings, each of which represents a character code of the encrypted text.

Let Key be a string representing the key (passcode) for the encrypted document.

Let DecryptedText be a string of text which will hold the result of decrypting the encrypted text.  Initially it is set to the empty string "".

Let EncryptedTextLength be the number of characters in EncryptedText.

Let KeyLength be the number of characters in Key.

Let Index be an integer used to index EncryptedTextArray.

Since we are indexing an array this time, rather than a string, our index will begin at 0 and end at EncryptedTextLength - 1.

Set EncryptedTextArray to the result of calling Split on EncryptedText, using " " as the separator sequence.

For each integer between 0 and EncryptedTextLength - 1, starting with 0 and ending with EncryptedTextLength - 1, let Index be the aforementioned integer and do the following:

(A) Let CurrentCodeAsString be the string at Index in EncryptedTextArray.

(B) If CurrentCodeAsString can be converted into an Integer then do the following:

  1. Let CurrentCode be the integer value of CurrentCodeString.  Use CInt to do the conversion.

  2. Let CurrentKeyIndex be the 1 + the remainder of dividing Index by KeyLength.

  3. Let CurrentKeyChar be the character at CurrentKeyIndex in Key.

  4. Let CurrentKeyCharCode be the character code of the CurrentKeyChar (use Convert.ToInt to do the conversion).

  5. Let DecryptedCharCode be CurrentCode XOR CurrentKeyCharCode.

  6. Let DecryptedChar be the character represented by the character code DecryptedCharCode (use Convert.ToChar to do the conversion).

  7. Append DecryptedChar to the end of DecryptedText.