When I was a kid, I had this fascination with cryptography. I learned and used, as most kids to, the Caesar cipher first (using my trusty Captain Crunch Decoder Ring), then later learned and used the Affine cipher. It was great for passing notes in class when I was in elementary and secondary education. I even learned the ancient runes, and used those quite a bit too.
Since then, I've been fascinated by hand cipher techniques, and I've learned a few historical ones over the years. I've even invented my own hand cipher, even though I doubt it would show any form of cryptanalytic strength. While I don't do anything with hand ciphers practically, I still consider it a fun skill to have, whether or not it actually proves to be useful (when I was a Boy Scout, I always wanted to learn Morse Code, so I could tap out answers to a quiz or test in class to a fiend, and back to me without anyone knowing. How cool would that be?!).
While I know base-64 is not considered a cipher algorithm, I thought to myself that I don't know how to convert a string of ASCII text to base-64 by hand. So, I figured I might as well learn. It could be an interesting skill to add to my own hand cipher, and could even prove to be useful around the house. So, if you're curious, here we go.
STEP ONE: Know the ASCII code chart
I would recommend memorizing or printing out (and stuffing in your wallet) this chart here: http://en.wikipedia.org/wiki/File:ASCII_Code_Chart-Quick_ref_card.png. Reason being, is you need to covert the ASCII text to numerical binary. The chart linked to gives you the table on how to do it.
Really, you can use any standard ASCII chart that provides you with the decimal, octal or hexadecimal values of the character. So long as you can convert it to binary, that's all that matters. I like the linked chart above, because it gives it to me out the gate, which is one less conversion to worry about.
STEP TWO: Convert your ASCII string to numerical binary
This is the tedious part. It's going to take you some time to write down every character in 8-bit binary. I need to stress that you need to write down the FULL 8 BITS, even though the card linked to only gives you 7. So, the 8th bit will always be zero when writing down the full binary word. Here's a rundown of how you would read the card:
- Find the character you wish to convert
- Write down 0 + the first three binary bits on the top
- Write down the last four binary bits for that letter on the left
So, for example, the text "green" would be "01100111 01110010 01100101 01100101 01101110". Notice that each binary word is 8 bits, each with leading zeros. This should be the case for EVERY character you write down. Further, the space between letters is NOT ignored. It has the binary value of "00100000" ("SP" in the chart).
STEP THREE: Pad at the end as necessary with zeros
The total number of bits should be divisible by 6. If it is not, add the necessary zeros at the end until it is. So, for our example of "green", we have a total of 40 bits, which means we need to add two more zeros to make it divisible by 6 (42 divided by 6 is 7). It's important that you stop at the first multiple of 6, which means that you should never be adding more than 4 zeros. In fact, you will either be adding two zeros, four zeros, or none at all.
So, for "green" with padded zeros at the end, our binary string becomes: "01100111 01110010 01100101 01100101 01101110 00"
STEP FOUR: Divide your binary string into words of 6 bits
Because our binary string is now divisible by six, we want to make 6-bit words using the same string. So, for "green", I should end up with 7 total words (because I have 42 bits total in the string). As a result, "01100111 01110010 01100101 01100101 01101110 00" becomes "011001 110111 001001 100101 011001 010110 111000"
STEP FIVE: Convert your 6-bit words to decimal
Now we need to covert the newly created binary words into decimal. You need to know your binary to pull this off. Thankfully, this isn't too terribly difficult- you just need to know your powers of 2. So, our string of "011001 110111 001001 100101 011001 010110 111000" becomes "25 55 9 37 25 22 56".
STEP SIX: Convert decimal to ASCII
Now, we need to covert our newly calculated decimal numbers to ASCII, and we'll almost be finished. For this, we're going to use a different chart than what we started with. We need a chart that will correspond to our values, starting at 0 and ending on 63 (64 possible values, thus the reason it's called "base-64").
- If the value is between 0 and 25, then the character is uppercase "A-Z" respectfully.
- If the value is between 26 and 51, then the character is lowercase "a-z" respectfully.
- If the value is between 52 and 61, then the character is the numbers "0-9" respectfully.
- If the value is 62 or 63, then the character is "+" and "/" respectfully.
If that was confusing to you, see the table at http://en.wikipedia.org/wiki/Base64#Examples.
So, for our string of numbers "25 55 9 37 25 22 56", which came from the text "green", we see the following come out: "Z3JlZW4".
STEP SEVEN: Pad the string with "=" as necessary
The last step in your conversion is to pad the string with "=" as necessary, so the total number of your characters is divisible by four. Our base-64 string has only 7 characters, so we must add a "=" at the end to bring the total to 8 characters, which is indeed divisible by four. Thus, we would end up with "Z3JlZW4=" as the final result for "green".
QUICK EXAMPLE: "Attack at dawn!"
- Attack at dawn!
- 01000001 01110100 01110100 01100001 01100011 01101011 00100000 01100001 01110100 00100000 01100100 01100001 01110111 01101110 00100001
- 010000 010111 010001 110100 011000 010110 001101 101011 001000 000110 000101 110100 001000 000110 010001 100001 011101 110110 111000 100001
- No zero padding necessary
- 16 23 17 52 24 22 13 43 8 6 5 52 8 6 17 33 29 54 56 33
- No "=" padding necessary
The base 64 utilities that ship with GNU Coreutils and OpenSSL use a different padding at the end of the encoded string than just equal signs. I haven't parsed the code yet, so I don't know why this is, but from what I'm reading online, the standard is to use just "=", unless I'm missing something. If anyone knows why "K", "o=" and others show up, I'm all ears. Thanks.
Encoding text to base-64 certainly doesn't really yield any cryptographic strength, and there exist utilities for doing it on the computer. So, why bother learning it by hand? As stated earlier, it's a fun skill to have around the house. Combine it with other hand ciphers that you might already know, and you could have a decent algorithm on your hands (pun intended). Heck, let's see your English teacher decrypt your notes now!