Introduction To Haskell
Vignère Cipher

Introduction

The Vignère cipher is a polyalphabetic substitution cipher. That means that each plain text letter can be replaced by more than one different letter in the cipher text. It was popularised by Blaise de Vignère in the 19th century although the approach was detailed several centuries earlier. It represented a significant breakthrough in cryptography for the time and proved difficult to crack in the pre-computer era.

The basis of the cipher is a table known as the tabula recta. It is a table of cipher alphabets, 26 in total and is shown below.

Tabula Recta

Notice that each of the 26 rows contains a Caesar Shift alphabet. If you number rows from 0 to 25, the shift number of each of the alphabets is equal to its row number.

To encrypt a message with Vignère, you first need to select a keyword. The letters of the keyword are used to select a cipher alphabet to use for substitution with each letter.

This example uses the keyword SECRET and the message The secret is out.

Write out the message removing all spaces and non-letter characters.

THESECRETISOUT

Write out the letters of the keyword underneath each letter of the message. Start from the beginning of the keyword if you run out of letters,

THESECRETISOUT
SECRETSECRETSE

The letter in the keyword tells you which cipher alphabet to use. The first letter in the message, T will be encrypted using the alphabet in row L. The second letter of the message is encrypted using the alphabet in row E, the third with the alphabet in row M and so on.

THESECRETISOUT
SECRETSECRETSE
LLGJIVJIVZWHMX

Programming

import Data.Char

-- tidy up a string for processing
tidy :: [Char] -> [Char]
tidy = map toUpper . filter isLetter

-- encipher and decipher individual characters
encipher :: Char -> Char -> Char
encipher c k = chr ((mod  (ord c + ord k) 26) + ord 'A')
decipher :: Char -> Char -> Char
decipher c k = chr ((mod  (ord c - ord k) 26) + ord 'A')

-- encipher plain text using key
envig :: [Char] -> [Char] -> [Char]
envig plain key = zipWith (encipher) p kc
        where
            p = tidy plain
            kc = cycle (tidy key)

-- decipher cipher text using key
devig :: [Char] -> [Char] -> [Char]
devig plain key = zipWith (decipher) p kc
        where
            p = tidy plain
            kc = cycle (tidy key)

WinGHCI

The tidy function allows the plain text and key to be entered without case sensitivity. Starting from the right, the message string (a list of characters) is filtered into the letter characters. These are converted to uppercase by the map function.

The enciphering and deciphering functions work on characters. The c argument is a character from the message, the k character a character from the keyword. By examining the position of the two characters in the alphabet, an enciphered or deciphered character is determined.

The envig function uses the higer order function, zipWith. This takes two lists and uses them as arguments in a function to create a new list. The first list is the tidied plain text, the second is the tidied keyword cycled infinitely. Fortunately, the zipWith function stops when it reaches the end of the shortest list.

Challenge

Work out a way to group the output string into substrings of length 5.