Articles Archive
Articles Search
Director Wiki
 

Encryption Utility Lingo

June 13, 2001
by Michael Szabo

Background

Quite often in Lingo development, I come across a situation where we must save some data to the user's hard disk for later retrieval. Sometimes it's a high-score list from a game, user preferences for a GUI, or perhaps it's a database of email addresses and phone numbers. Often this information is sensitive enough that I don't want to make it easy for people to modify the contents, as is the case with a saved high-score. If I simply used the FileIO Xtra or setPref to save the user's score, what's to stop someone from opening the file, changing some numbers, restarting the game, and reposting their false score to the Internet? Although the chances this will happen are rare, after spending months to make a challenging game for the web, it would be a tragedy to see someone ruin the competitive community it's built by posting ridiculously high scores.

To help combat cheating and casual hacking in Director-developed projects, I offer this set of utility functions that help obscure your private data from prying eyes. Using these functions and the methods described below, you can easily encrypt your data before it's saved to the user's computer. The encryption is pretty basic, but should deter most would-be snoopers. Be warned, however, that like all encryption methods, it is not infallible. A skilled hacker could no doubt find his/her way around these functions. But really...what skilled hacker even cares about messing around with your saved preferences? They have bigger and better things to do. This proceedure is mainly targeted at keeping any meddling punks from effortlessly reverse-engineering your hard work and making you look like a fool.

View the code in a new window or download the text file and a D7 cast for Mac or Windows.

How to Use It

Encrypting your data

The EncryptString function accepts two parameters. The first is a text string representing the text you want to protect, such as a high score ("632100"). The second parameter is your encryption key (think of it like a password) that will be used to garble the first parameter. Make the key as long as you like. Longer keys offer marginally better protection, but don't bother using more than 12-16 chars since there's really no benefit. The key string you use to encrypt your data is the same string used to decrypt the data. In order to ensure that the data you save to the hard disk can be reloaded later, make sure you choose a password key that will not change over time, or from one session to another. Keep in mind the key is case-sensitive.

The easiest method is to choose a hard-coded word as a key. For example, "11HanSoloRules!22" would work just fine. Here's an example:

sTest = EncryptString ( "Testing", "11HanSoloRules!22" )
put sTest
-- "eT; = "

And now, to get the original data back, call the same function again using the same key, but send the encrypted text.

put EncryptString ( sTest, "11HanSoloRules!22" )
-- "Testing"

If the idea of hard-coding your key seems too insecure to you, you can opt to be even craftier and use Lingo to dynamically create a key. Again, be careful not to create a key that will change before you need it again. For example, choosing string (the milliseconds) as your encryption key would only be valid for merely one millisecond. Not too useful! Plus, since the decryption process has no error-checking or verification built-in, the saved data will seem to have decrypted just fine. Until you actually examine it and see a mass of illegible garbage.

Since saved preference files almost never move from one computer to another, you could probably get away with (the environment).platform as part of your key. Combine that with another machine-specific chunk of text and you've got a pretty good key. For example:

sTest = EncryptString( "Testing", (the Environment).platform & "00" & the RunMode )
put sTest
-- " "

Now, at any time in the future, you can retrieve the saved data by passing the encrypted text to the EncryptString function with the exact same key. Example:

put EncryptString( sTest, (the Environment).platform & "00" & the RunMode )
-- "Testing"

If you want to save a property list for later retrieval, first convert the property list to a string using Director's built-in Lingo, then pass the string to EncryptString.

lMyPet = [ #AnimalType: #DOG, #AnimalName: "Fluffy", #IsAnnoying: TRUE ]
sTest = EncryptString ( lMyPet.string, "MySecretKey" )

Date Output

Once you've run your data through the encryption process, the new string will contain many non-alphanumeric characters. Chances are, it won't even display properly when you try to put the contents in the Message window. That's a problem, because setPref doesn't like those quirky characters and will most likely fail if you send it your encrypted string. One more step is required before you can save your data. You have to encode it first.

The EncodeString function takes your encrypted string and modifies it so that it only contains simple alphabetic characters. Once encoded, the setPref command will have no problem writing your data to the disk. One thing to be wary of...encoding your string will effectively double its length. Sending too large a string (>32K) to setPref may fail. In cases where you have a lot of data, you ought to consider saving it in chunks to avoid any problems.

The encode process works as follows:

sTest = EncryptString ( "Hello there!", "TESTKEY" )
put sTest
-- " ?8$e-< !1j"

sTest = EncodeString ( sTest )
put sTest
-- "bmcadpdicegfcndmcacbdbgk"

 

Do you think anyone will want to bother messing with your prefs if they look like that?! Hell no! Now you can use setPref...

SetPref ( "MySavedData", sTest )

That's it! The encrypted data is saved to the hard disk. To reverse the process use the companion DecodeString function as follows:

sInString = GetPref( "MySavedData" )
sInString = DecodeString( sInString )
sInString = EncryptString( sInString, "TESTKEY" )
put sInString
-- "Hello there!"

Conclusion

Some of my fellow developers may think using this method is overkill just to protect some high scores or the structure of a saved property list. I understand that point of view, but I disagree. Using the above methods will help protect you from casual hackers before they have a chance to mess up your efforts. Why wait until you're burned to take some precautionary measures to thwart all those people with bad intentions and too much time on their hands? I'm not paranoid by any means, but I strongly detest the thought of someone spoiling my work. I also feel that by protecting my saved data, I'm making my projects tidier and more professional. By using this method, you have a good chance of discouraging snoopers and maintaining the quality of your work. It's a no-brainer!

DISCLAIMER: I accept no responsiblility for harm resulting from the misuse of this information. Use at your own risk!

Michael Szabo, the self-proclaimed 'CheezyWhiz', is an award-winning multimedia and web game developer in Los Angeles, CA. His recent projects include the 3D 'SkyRacer Impulse' for shockwave.com and the quirky 'Axercise' for the eCampus.com Phun-Lab. Try out his games and browse his other work at www.cheezywhiz.com.

Copyright 1997-2024, Director Online. Article content copyright by respective authors.