Substitution Cipher Implementation - File Encryption/Decryption



Task

Encrypt a input/source file by replacing every upper/lower case alphabets of the source file with another predetermined upper/lower case alphabets or symbols and save it into another output/encrypted file and then again convert that output/encrypted file into original/decrypted file.

This type of Encryption/Decryption scheme is often called a Substitution Cipher.



Related tasks

 Caesar cipher
 Rot-13
 Vigenère Cipher/Cryptanalysis


See also

 Wikipedia: Substitution cipher


import Data.Char          (chr)
import Data.Maybe         (fromMaybe)
import Data.Tuple         (swap)
import System.Environment (getArgs)
 
data Command = Cipher String | Decipher String | Invalid
 
alphabet :: String
alphabet = chr <$> [32..126]
 
cipherMap :: [(Char, Char)]
cipherMap = zip alphabet (shuffle 20 alphabet)
 
shuffle :: Int -> [a] -> [a]
shuffle n xs = iterate go xs !! n
  where
    go [] = []
    go xs = go (drop 2 xs) <> take 2 xs
 
convert :: Eq a => [(a, a)] -> [a] -> [a]
convert m = map (\x -> fromMaybe x (lookup x m))
 
runCommand :: Command -> String
runCommand (Cipher s)   = convert cipherMap s
runCommand (Decipher s) = convert (swap <$> cipherMap) s
runCommand Invalid = "Invalid arguments. Usage: simplecipher c|d <text>"
 
parseArgs :: [String] -> Command
parseArgs (x:y:xs)
  | x == "c" = Cipher y
  | x == "d" = Decipher y
  | otherwise = Invalid
parseArgs _ = Invalid
 
main :: IO ()
main = parseArgs <$> getArgs >>= putStrLn . runCommand