Several years ago I foolishly embarked on a project to create my own encryption scheme. The problem with doing that is that unless you're a hotshot mathematician, which I'm not, you're bound to fail miserably. However, a few weeks ago while watching too many chevrons fly across the screen during SciFi Friday, I became over-stimulated and couldn't get the thought of obfuscating everyday text out of my mind. I use the word "obfuscation" because I don't think this method qualifies as true encryption, but then, I don't work for the NSA. And I doubt my idea is original. Anyway, if I'm not mistaken, this technique is similar to producing a symmetric cipher in which the same key is used to encrypt and decrypt plain text files. However, this method uses a pass phrase to choose the keys, which I refer to as key lines, that will be used to obfuscate plain text messages. For lack of a better name, I will refer to this cipher as the SG1 Cipher.
At this point I should mention the proof of concept code is written in Java. And yes, I know I'll be condemned to deprecation hell for using techniques the Java Developer's Mafia persecute others of my ilk for using. The point is the SG1 cipher can easily be rewritten into any other programming language, but if anyone out there wants to slap lipstick on this pig, go right ahead.
The code that generates the keys and does the encode/decode routines depend on a string variable called "charlist". In the code example the value of this variable is set to the following:
charlist="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*+-<>.,?/|][_={}:()~;' \"";
Note the use of the '\' to escape the double quotes. Depending on the programming language used, you may need it. Here is the code flow that generates the SG1 cipher:
GENERATING PASSPHRASEKEY:
1. for (int i=0;i<charlist.length();i++)
2. Generate a random number from 0 to charlist.length-1. Keep in mind
that most programming languages use zero-based indexing.
3. Pull out a char from charlist that is located at that random number
index.
4. Check to make sure that char hasn't been chosen yet.
5. If it hasn't add to this key line. If it has, decrement the counter
variable i and redo.
6. Print out the passphrasekey to standard out.
The code above is the same code used to generate the key lines for the SG1 cipher block. The only difference is that for each new key line, the first char must be checked to make sure it hasn't been used in a previous key line. Each keyline will begin with its own unique char that will be used to identify it. So, you will have an "L" key line, a "2" key line, a "!" key line and so forth. Also, the number of key lines will always equal the number of chars in "charlist".
Dearest Samantha. I cannot stand it any longer. Though the powers that be keep jerking us around, I cannot wait another 8 seasons to hold you in my arms. Meet me in the Gate Room at midnight. Warmest Regards- MacGyver.
The first thing that must take place is that the pass phrase we chose above must be encoded. For instance, let's take the first char 'D'. It is encoded by finding it's numerical index position in the passphrasekey line and pulling out the char in the 'D' key line in the SG1 cipher block at the same numerical index. For these purposes, let's say the answer is 42 (hg2g >:P). The char at index 42 in the 'D' key line for this example might be 'l'. The passphrase is encoded char by char in that manner and might look like this:
D4n1el,ItsWhatw3d0 => l;#aGbOUf2z/3hAtPR
Those chars in the new encoded passphrase will become the list of key lines repeating in that sequence to encode each char in the message. For instance, the first letter in our message is 'D'. We already established that its index is 42 in the passphrasekey line. But, instead of looking to the 'D' key line, we go to the 'l' key line and pull out that char at numerical index 42 to represent 'D'. We move to the next key line listed, which is ';' and do the same for the next char in the original message, which is 'e', and so on until the message is encoded. But let's not encode the message just yet. It's not enough to encode our plain text file which may be easily decoded. Let's pad the message with random chars before and after our pre-encoded message to further obfuscate what encoded chars represent our message. In my java example I use between 150-300 random number of chars, randomly generated, to prepend and append to the message. I also use delimeters to mark the beginning and end of the message before encoding the entire thing using the previously describe method. But, one word of caution- choose your delimiters carefully! In my java proof-of-concept code, this is the command that one runs when encoding:
java sg1 -e [cleartext.txt] [sg1keyfile] [encodedtext.txt]
java sg1 -d [encodedtext.txt] [sg1keyfile] [cleartext.txt]
This is just an exercise in obfuscation. You probably should not use the SG1 cipher in real life since my guess is that it would be easily broken. There are also other issues involved such as using a long pass phrase, protecting the pass phrase itself, and protecting the key file, all of which would have to be taken into account. But let's continue the dialing sequence.
charlist="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*+-<>.,?/|][_={}:()\~;' È�[8;1HÐÛÔíäû£ÜÊÖ¼Òïºö°ÉìùÃ˾ݵÀóþâÚêÕýçÓú½ñÑᢱÁð¡Äÿ¿\"";
(Warning, the line above may not display correctly in your browser)
When generating the key, this will result in key line lengths of 143 chars with 143 key lines in the main SG1 cipher block. My guess is you can extend that range to the full complement of Unicode characters that are available. As for the java code, you only need to update the "charlist" variable and recompile the code. You must keep in mind that the keys you generate must use the same characters that you use to encode/decode data, which means that the "charlist" variable must be the same in both java programs that generate the key file and the one that actually does the encoding/decoding.