View on GitHub

CryptoAlgebra

Time for our first cipher, the Shift Cipher!

The basics

The idea behind the shift cipher is that we adjust our previous mapping: $$ \begin{array}{c c c c} a & b & c & \cdots & x & y & z \\ \downarrow & \downarrow & \downarrow & \cdots & \downarrow & \downarrow & \downarrow \\ 0 & 1 & 2 & \cdots & 23 & 24 & 25 \\ \end{array} $$ by adding some number (called the key), modulo 26.

Lets take the example where our key is 2. $$ \begin{array}{c c c c c c c} a & b & c & \cdots & x & y & z \\ \downarrow & \downarrow & \downarrow & \cdots & \downarrow & \downarrow & \downarrow \\ 2 & 3 & 4 & \cdots & 25 & 0 & 1 \\ \end{array} $$

Encryption

Abstracting the pattern away from out previous example, we can make the following encryption function: $$ E(x) = (x + k) \mod 26 $$

Generally speaking, you want $0 \leq k \leq 25$, but really since we are modding by 26, it doesn’t matter. Any $0 > k_1 > 25$ has a corresponding $0 \leq k \leq 25$

Let us write a function to shift a single letter by a given key, resulting in an encrypted letter.

-- file : CryptoTools.hs

shift :: Int -> Int -> Int
shift k x = (x + k) `mod` 26

Now we have a simple function that shifts individual characters. Also recall that we have charToIdx and idxToChar from the Establishin Conventions post.

With these tools we can create our final encryption function:

-- file : shift.hs
import CryptoTools

shift_encrypt :: Int -> String -> String
shift_encrypt k cs = map (idxToChar . shift k . charToIdx) (clean cs)

Testing shift_encrypt

ghci> shift_encrypt 2 ['a'..'z']
"CDEFGHIJKLMNOPQRSTUVWXYZAB"

Just like the mapping given at the begining of this post!

Decryption

So what happens if we are given the ciphertext "ZHGLGLW", and know that the key is 3? Well, we need a corresponding shift_decrypt.

Mathematically speaking the decryption function must be defined such that the composition of the two is the identity function.

That is: (shift_decrypt k . shift_encrypt k) is the same as id

Consider $$ E^{-1}(x) = (x - k) \mod 26 $$

With the same stipulations as our encryption function.

Lets test whether or not our function composition is in fact the identity function:

$$ E^{-1}(E(x)) \\ = E^{-1}((x + k) \mod 26) \\ = (((x + k) \mod 26) - k) \mod 26 \\ = x \mod 26 \\ = x, \text{ since } x \in \mathbb{Z}_{26} $$

Now we can write out the shift_decrypt function using $ E^{-1} $

shift_decrypt' :: Int -> String -> String
shift_decrypt' k cs = map (idxToChar . shift (-k) . charToIdx) (clean cs)

Or we can make the clever observation that shift_decrypt is very simply related to shift_encrypt

-- file : Shift.hs

import CryptoTools

shift_decrypt :: Int -> String -> String
shift_decrypt k cs = shift_encrypt (-k) cs

Testing shift_decrypt

So does it work?

Lets check that ciphertext given at the begining of this section:

ghci> shift_decrypt 3 "ZHGLGLW"
"wedidit"

Thoughts

I hope this first cipher wasn’t too slow. We are, after all, still on cryptosystems that are hundreds or thousands of years old. The pace will pick up, and this blog will increase in computational and mathematical difficulty, but hopefully remains (or becomes at some point) understandable.

The Code

Get the full code on my github

If you clone the repository, the command to use to load this file would be:


$ pwd
/foo/bar/CryptoAlgebra/Classical_Cryptography
$ ghci -i.. Shift.hs
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 2] Compiling CryptoTools      ( ../CryptoTools.hs, interpreted )
[2 of 2] Compiling Shift            ( Shift.hs, interpreted )
Ok, modules loaded: Shift, CryptoTools.
*Shift>