Sunday, February 24, 2013

Living my LiveCode Dream: Encryption Version 2.0



In my last post, I made it clear that updating line 7 in the code to use different "encryption" techniques is a very poor strategy. And, what about giving the user the option of what to encrypt?

So, version 2.0 is here to the rescue!


As this screenshot shows, the user now has control over the two options for what to reveal in the target word, or to choose neither. To do this, I added two new check box buttons: btnNumbers and btnCapitals. I tried to use good naming conventions, hence I put the prefix "btn" (short for "button" of course) in front of each. The important thing to remember with a check box button is that when it is checked, the "hilite" of it is true; likewise, when not checked, its "hilite" is false.

OK, let's take a look at the modified code of the button "encrypt":

-----------------------------------------------------------------------------------------------

global varChar, varLength, varWord, varWordEncrypt, varEncrypt

on showCapitals
   if (charToNum(char varChar of varWord) >64) and (charToNum(char varChar of varWord) <91) then
      put varWordEncrypt & char varChar of varWord into varWordEncrypt
      put false into varEncrypt
   end if
end showCapitals

on showNumbers
   if (charToNum(char varChar of varWord) >47 and charToNum(char varChar of varWord) <58) then
      put varWordEncrypt & char varChar of varWord into varWordEncrypt
      put false into varEncrypt
   end if
end showNumbers

on mouseUp
   put empty into varWordEncrypt
   put line 1 of field "target" into varWord
   put the length of varWord into varLength
   repeat with varChar = 1 to varLength
      put true into varEncrypt
      if hilite of button "btnCapitals" is true then showCapitals
      if hilite of button "btnNumbers" is true then showNumbers
      if varEncrypt is true then put varWordEncrypt & "*" into varWordEncrypt
   end repeat
   put varWordEncrypt into line 1 of field "result"
end mouseUp

-----------------------------------------------------------------------------------------------

First, notice that I had to declare a bunch of global variables. This was not necessary in version 1.0 because everything was happening inside of a single handler (i.e. on mouseUp). Now, these variables are used in a bunch of places, so they need to be global variables.

The main difference between the code here and that in version 1.0 shown in my previous post is that line 7 is now replaced by lines 7 and 8:

     if hilite of button "btnCapitals" is true then showCapitals
     if hilite of button "btnNumbers" is true then showNumbers

Each of these two lines first check to see if the check box buttons are checked and if they are (i.e. if true), then each executes a custom procedure: showCapitals and showNumbers. Think of custom procedures as "teaching" LiveCode new vocabulary words to add to its "language" (yes, think of yourself as a language teacher and LiveCode is your student).

When a new word is encountered by LiveCode, it checks to see if the word has been previously "defined." As you can see, both have been defined just above the "on mouseUp" script. If you compare the script of these two procedures to line 7 in version 1.0, you will find they are almost identical.

But, you will notice I had to create a new variable: "varEncrypt". This is another one of those true/false variables. Notice that at the start of each repeat loop, it is set to true. Also notice that if either the showCapitals or showNumbers procedure is executed, then it is set to false. This is important because if either gets executed, we obviously don't want the character to be displayed as an asterisk. Consequently, line 9 in the "on mouseUp" script will only execute when varEncrypt is true.

Finally, I added the following code to the card script:

on openCard
   set the hilite of button "btnNumbers" to false
   set the hilite of button "btnCapitals" to false
end openCard

This script just turns both check box buttons off when the card is opened. That seemed the best way to start.

I hope you will agree that this version 2.0 is a huge improvement over version 1.0. The use of the showCapitals and showNumbers procedures is much cleaner and easier to follow. If I wanted to add an option to only show vowels, I would just add another check box button called something like "btnVowels" and a procedure called something like "showVowels," then insert the following line of code into the button script:

      if hilite of button "btnVowels" is true then showVowels

And, giving the user the option to control the code always fills me with delight because it transforms a simple piece of code into a powerful tool.

In my next post, we'll finally do the obvious: write some code that reveals one of the target word's characters at random. I can hardly wait.

Tuesday, February 19, 2013

Living my LiveCode Dream: Encryption

As I wrote recently, I had a little dream of creating I've a little encryption app that would store one's usernames and passwords, but with the option to "encrypt" them a little bit as a way to disguise the full information. I find myself constantly forgetting which username and password go together for all of the various accounts I have. Even though there appears to be no need for this app (given how many free apps are already out there that do this sort of thing), I thought it still would be a good little project to explore.

First, an all important disclaimer. This program does not, in fact, do any encryption in the technical sense. "Disguise" would probably be a better word. That is because the "identity" of the password is contained in one variable in its raw (unencrypted) state, while another variable is used to reveal its identity. OK, enough already, on with the show.

So, here is my first attempt with a file called "lloydencryption1.livecode." Here is a screen shot of the first card:









As I hope you can surmise, you enter a word in the target field, then press the "encrypt" button to encrypt the word by changing every non-capital letter and non-number into an asterisk.

















All of the code is found in the "encrypt" button:

on mouseUp
   put empty into varWordEncrypt
   put line 1 of field "target" into varWord
   put the length of varWord into varLength
   repeat with varChar = 1 to varLength
      //Only show capital letters and numbers:
      if (charToNum(char varChar of varWord) >64 and \
      charToNum(char varChar of varWord) <91) or \
      (charToNum(char varChar of varWord) >47 and \
      charToNum(char varChar of varWord) <58)
         then
         put varWordEncrypt & char varChar of varWord into varWordEncrypt
      else
         put varWordEncrypt & "*" into varWordEncrypt
      end if
   end repeat
   put varWordEncrypt into line 1 of field "result"
end mouseUp

First, note that the symbol \ simply allows for a very long line of code to be broken into separate lines. But, let's start at the top and work our way down.

Line 1: on mouseUp
Line 2: After pressing the button, the first line clears out any contents that might have been in the variable "varWordEncrypt."
Line 3: The contents of the field "target" are put into a local variable "varWord."
Line 4 determines the length of the target word, which is very important because the very next line depends on this number to determine the total number of loops to repeat.
Line 5 triggers a loop that repeats for the number of characters in the word.

Now, the next bunch of lines depends on something called ASCII code. Every character on the keyboard has an associated ASCII code.  For example, a lower case "a" has the ASCII code of 97 whereas an upper case "A" has the ASCII code of 65. The numbers 0-9 have ASCII codes ranging from 48-57. How can you determine the ASCII code for a character? You could either consult a Web page with the information, such as http://www.ascii-code.com/ or, if you are really geeky, you could create your own converter (which I actually did -- it's card 2 of the stack). (Note: Apparently, ASCII has generally been replaced with Unicode, but that's not too important right now. I just like ASCII, OK?)

Line 7 is the "encryptor" line. It's long and very unelegant, but we'll improve upon this in a later post. For now, let's see what it does. First, notice that line 7 along with lines 8-12 have this construction:

 if (this and that is true) or (this and that is true)
         then
         do this
      else
         do this instead
      end if

Let's add more pseudocode to line 7. It really translates as the following:

 if (the character is an uppercase letter) or (the character is a number)

The function "charToNum" takes a character and returns the ASCII code of it. Now, remember for a moment that the ASCII for a capital "A"is 65 and the ASCII for a capital "Z" is 90 as we dissect the following bit of code:

charToNum(char varChar of varWord)

Notice that the repeat loop begins with 1 and ends with the length of the word. So, if I enter "Lloyd1", the length (held by the variable "varLength" is 6). Repeat loops such as this are really fun and useful. The loop begins by putting the value of 1 into the variable varChar, then increases by 1 at each and every loop until the loop ends. So, at the first pass, the code "charToNum(char varChar of varWord)" translates as "give me the ASCII code of character 1 of the contents of varWord. At loop 2, it gives us the ASCII code of the second character, and so on until the loop ends when we run out of characters.

So, if the ASCII code for the character is greater than 64 (i.e. 65) and less than 91 (i.e. 90), then it must be an uppercase letter. Similarly, if the ASCII code is greater than 47 (i.e. 48) and less than 58 (i.e. 57), then the character must be a number. That's exactly what line 7 is checking. If all of this is true, then line 9 simply adds that character to a string of characters it is building in the variable "varWordEncrypt." (Note that the ampersand & is the concatenation symbol which basically "adds" one string to another.  If Line 7 is false, then line 11 puts an asterisk in place of the character.

Line 13 ends the repeat command, either sending LiveCode back to Line 5 to start the next loop or the loop ends.

Line 14: It's important to remember that this line only is executed after all of the looping concludes. This line takes the result of the looping -- the building, character by character, of the variable "varWordEncrypt" -- and puts into the line 1 of the field target.

(Whew! As always, it's harder to write up an explanation of the code than to actually do the coding!)

Now, you might be asking, what if i wanted to encrypt only lowercase letters, or maybe only the vowels, or only constants, or only prime numbers, etc., etc. One answer would be to keep changing line 7 accordingly. But, that's a pain, plus how about if I want to give the user the option of what to encrypt, including encrypting everything or nothing? Line 7, as it is currently constructed, just won't do.

In one of my next postings, I will share a more elegant way to do this in the context of giving the user the option of what (or what not to) encrypt.

By the way, why am I going to all this trouble when my dream of creating the encryption app is a pipe one. Two reasons. One, it's a lot of fun doing it. If that is not reason enough, then my second is that I see this as a wonderful gaming feature that I could use at some point. Imagine being in a virtual world where you are given an encrypted message and you must go on a quest to unlock the code. It would be cool to slowly see a message emerge as you meet challenges in the world, something like:

**********
.
.
.
.
*o*o**ua*e*
.
.
.
.
gotosquare*
.
.
.
.
gotosquare7
And, I'm sure I can think of other good uses of this as well. But, I'm really just doing it because it is fun.

P.S. Go to this stack's second card to find a little "ASCII code generator" that you might find helpful.