Programming Praxis – Autokey

In today’s Programming Praxis we have another cipher algorithm. Let’s get started.

A quick import:

import Data.Char

First of all, we need a function to add and subtract characters.

combine :: (Int -> Int -> Int) -> Char -> Char -> Char
combine f a b = chr $ mod (f (ord a) (ord b) - 2 * 65) 26 + 65

Encrypting or decrypting is just a matter of using this combine function on all the letter pairs of the key and the message.

cipher :: (Int -> Int -> Int) -> String -> String -> String
cipher f key msg = zipWith (combine f) (clean msg) (clean key)
                   where clean = map toUpper . filter isLetter

When encrypting, we can simply append the message to the key.

encrypt :: String -> String -> String
encrypt key msg = cipher (+) (key ++ msg) msg

When decrypting, we instead need to append the unencrypted message, which we do not have yet. Fortunately, thanks to lazy evaluation we can simply recursively call the decrypt function. This means it will produce a stack overflow when fed an empty key, but since that would be useless anyway we don’t really care.

decrypt :: String -> String -> String
decrypt key msg = cipher (-) (key ++ decrypt key msg) msg

All that’s left is to test our functions:

main :: IO ()
main = do print $ encrypt "BONSAI" "Pablo Picasso"
          print $ decrypt "BONSAI" "QOODOXXCBDGD"

That seems to work just fine. Another one down.

Tags: , , , , , , ,

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: