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.
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)
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.