Implementing a Basic Caesar Cipher in Python

Written by Dan Sackett on January 16, 2015

Continuing on from yesterday, I wanted to introduce the Caesar cipher and give an example of how to implement it in Python.

Much like the substitution cipher from yesterday's post, the Caesar cipher transforms the alphabet creating a mapping from keys to different values making it act much like a substitution cipher. Where it differs however is how we generate this new key.

Instead of randomizing our keys and reassigning them as values, the Caesar cipher simply rotates the alphabet to the right. For instance:

A == B
B == C
C == D
...
Z = A

As we can see here, we rotated the alphabet once which subsequently assigned our values as KEY + 1. So now when we are encrypting plaintext, we simply substitute our values and we're done. As we can see, this process is very primitive in nature and way less secure than a typical substitution cipher. In fact, an attack on this cipher is quite easy. We can do a short brute force attack trying each rotation of the alphabet until we see a plaintext message that makes sense. Once we do, we have our key thanks to the rotation being uniform across the set.

The primitive nature of this cipher is due to its namesake.

It was Julius Caesar who encrypted all of his messages this way it seems. He was famous for a simple single rotation key which at the time was very hard to understand. This was mostly due to the lack of educated people in the world. As Caesar passed messages, those that didn't understand believed that it was another language and carried on.

While smart for the time, I'll reiterate that this is one of the fastest ciphers to solve. Still, it doesn't hurt to see it in action as it can be a fun puzzle.

plaintext  = ATTACKATDAWN
alpha      = ABCDEFGHIJKLMNOPQRSTUVWXYZ
key        = BCDEFGHIJKLMNOPQRSTUVWXYZA
ciphertext = BUUBDLBUEBXO

As we see, we shifted our alphabet once and use our key to substitute the new letters to create our ciphertext. If you're a math person, we have a simple formula that can help you determine the new letter as well:

Given x is the current letters index in regards to our alphabet and n is the rotation:
E(x) = (x + n) % 26
D(x) = (x - n) % 26

With this algorithm, we can build ourselves a simple script in Python that will encrypt and decrypt our data for us:

key = 'abcdefghijklmnopqrstuvwxyz'

def encrypt(n, plaintext):
    """Encrypt the string and return the ciphertext"""
    result = ''

    for l in plaintext.lower():
        try:
            i = (key.index(l) + n) % 26
            result += key[i]
        except ValueError:
            result += l

    return result.lower()


def decrypt(n, ciphertext):
    """Decrypt the string and return the plaintext"""
    result = ''

    for l in ciphertext:
        try:
            i = (key.index(l) - n) % 26
            result += key[i]
        except ValueError:
            result += l

    return result


def show_result(plaintext, n):
    """Generate a resulting cipher with elements shown"""
    encrypted = encrypt(n, plaintext)
    decrypted = decrypt(n, encrypted)

    print 'Rotation: %s' % n
    print 'Plaintext: %s' % plaintext
    print 'Encrytped: %s' % encrypted
    print 'Decrytped: %s' % decrypted

Digesting this, we see that we first define our alphabet as a variable key. We then build our encryption function which is a little more advanced than a single word scheme. In this example, I'm checking if the value exists in our alphabet and if it doesn't then I want to simply output that character instead of the encrypted character. This will allow us to use punctuation, space, etc.

We apply our algorithm to each letter of the plaintext and return a new concatenated string as our ciphertext. To decrypt it, we simply do the opposite (subtracting the rotation) and we get our message back.

We can run the program and see an example here:

show_result('the grass is always greener', 5)

We want to encrypt the message "the grass is always greener" and do so by shifting our alphabet 5 times. We then get:

Rotation: 5
Plaintext: the grass is always greener
Encrytped: ymj lwfxx nx fqbfdx lwjjsjw
Decrytped: the grass is always greener

This works! As we can see, this is very easy to implement which also shows how easy it really is to break as well. For those that don't want to write a program to do this, there is a Caesar cipher provided in the standard library in Python called rot13 which translates to "rotate 13" defining how the key works. Be warned though as this is only supported in Python 2.x:

>>> 'the grass is greener'.encode('rot13')
'gur tenff vf terrare'

Conclusion

Seeing how the Caesar cipher works, I hope you'll come back tomorrow to understand how the Vigenere cipher works which actually is many Caesar ciphers chained together. As with the last post, you can checkout some crypto stuff (including code) in a Github repo. I'll leave you with a special message which is encoded in the Caesar cipher I've provided.

ufekwfixvkkfuizebpflifmrckzev

Let me know what the message says and where it's from ;)


python cryptography

comments powered by Disqus