-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | An educational tool for studying classical cryptography schemes. -- @package crypto-classical @version 0.0.3 module Crypto.Classical.Util letter :: ℤ / 26 -> Char int :: Char -> ℤ / 26 -- | Must be passed a number coprime with 26. inverse :: ℤ / 26 -> ℤ / 26 prng :: IO SystemRNG -- | The sequence (r1,...r[n-1]) of numbers such that r[i] is an -- independent sample from a uniform random distribution [0..n-i] rseq :: CPRG g => g -> Integer -> [Integer] -- | Invert a Map. Keys become values, values become keys. Note that this -- operation may result in a smaller Map than the original. mapInverse :: (Ord k, Ord v) => Map k v -> Map v k -- | Compose two Maps. If some key v isn't present in the second -- Map, then k will be left out of the result. -- -- 2015 April 16 @ 13:56 Would it be possible to make a Category for Map -- like this? compose :: (Ord k, Ord v) => Map k v -> Map v v' -> Map k v' -- | An alias for compose. Works left-to-right. (|.|) :: (Ord k, Ord v) => Map k v -> Map v v' -> Map k v' -- | Zip a list on itself. Takes pairs of values and forms a tuple. -- Example: -- --
-- >>> uniZip [1,2,3,4,5,6] -- [(1,2),(3,4),(5,6)] --uniZip :: [a] -> [(a, a)] module Crypto.Classical.Shuffle -- | Given a sequence (e1,...en) to shuffle, its length, and a random -- generator, compute the corresponding permutation of the input -- sequence. shuffle :: CPRG g => g -> [a] -> Integer -> [a] instance Show a => Show (Tree a) module Crypto.Classical.Types -- | A Cipher must be able to encrypt and decrypt. The Cipher type -- determines the Key type. class Key k => Cipher k a | a -> k encrypt :: Cipher k a => k -> ByteString -> a ByteString decrypt :: Cipher k a => k -> ByteString -> a ByteString -- | Keys can appear in a number of different forms. E.g. a single number, -- a tuple, a mapping, etc. Each needs to be interpreted uniquely by a -- Cipher's encrypt and decrypt algorithms. class Key a key :: (Key a, CPRG g) => g -> a -- | Essentially the machine itself. It is made up of: 1. Three rotor -- choices from five, in a random placement. 2. Initial settings of those -- Rotors. 3. The Reflector model in use. 4. Plugboard settings (pairs of -- characters). data EnigmaKey EnigmaKey :: [Rotor] -> [Char] -> Reflector -> Plugboard -> EnigmaKey _rotors :: EnigmaKey -> [Rotor] _settings :: EnigmaKey -> [Char] _reflector :: EnigmaKey -> Reflector _plugboard :: EnigmaKey -> Plugboard -- | A Rotor (German: Walze) is a wheel labelled A to Z, with internal -- wirings from each entry point to exit point. There is also a turnover -- point, upon which a Rotor would turn its left neighbour as well. -- Typically said turnover point is thought of in terms of letters (e.g. -- Q->R for Rotor I). Here, we represent the turnover point as a -- distance from A (or 0, the first entry point). As the Rotor rotates, -- this value decrements. When it rolls back to 25 (modular arithmetic), -- we rotate the next Rotor. -- -- Our Rotors are letter-agnostic. That is, they only map numeric entry -- points to exit points. This allows us to simulate rotation very simply -- with Lenses. data Rotor Rotor :: Text -> ℤ / 26 -> Map (ℤ / 26) (ℤ / 26) -> Rotor _name :: Rotor -> Text _turnover :: Rotor -> ℤ / 26 _circuit :: Rotor -> Map (ℤ / 26) (ℤ / 26) -- | A unmoving map, similar to the Rotors, which feeds the electrical -- current back into Rotors. This would never feed the left Rotor's -- letter back to itself, meaning a plaintext character would never -- encrypt to itself. This was a major weakness in scheme which allowed -- the Allies to make Known Plaintext Attacks against the machine. type Reflector = Map (ℤ / 26) (ℤ / 26) -- | A set of 10 pairs of connected letters which would map letters to -- other ones both before and after being put through the Rotors. The -- remaining six unpaired letters can be thought of mapping to -- themselves. type Plugboard = Map (ℤ / 26) (ℤ / 26) name :: Lens' Rotor Text turnover :: Lens' Rotor ((/) ℤ 26) circuit :: Lens' Rotor (Map ((/) ℤ 26) ((/) ℤ 26)) rotors :: Lens' EnigmaKey [Rotor] settings :: Lens' EnigmaKey [Char] reflector :: Lens' EnigmaKey Reflector plugboard :: Lens' EnigmaKey Plugboard instance Key EnigmaKey instance Eq EnigmaKey instance Show EnigmaKey instance Eq Rotor instance Show Rotor instance Key [ℤ / 26] instance Key (Map Char Char) instance Key (ℤ / 26, ℤ / 26) instance Key (ℤ / 26) module Crypto.Classical.Cipher.Affine -- | An Affine Cipher is a non-random Substitution Cipher, such that a -- character x is mapped to a cipher character according to the -- equation: -- -- f(x) = ax + b (mod 26) -- -- Also known as a Linear Cipher. newtype Affine a Affine :: a -> Affine a _affine :: Affine a -> a affine :: Iso (Affine a_acIg) (Affine a_acLQ) a_acIg a_acLQ instance Cipher (ℤ / 26, ℤ / 26) Affine instance Monad Affine instance Applicative Affine instance Eq a => Eq (Affine a) instance Show a => Show (Affine a) instance Functor Affine module Crypto.Classical.Cipher.Caesar -- | A simple Shift Cipher. The key is a number by which to shift each -- letter in the alphabet. Example: -- --
-- >>> encrypt 3 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ^. caesar -- "DEFGHIJKLMNOPQRSTUVWXYZABC" --newtype Caesar a Caesar :: a -> Caesar a _caesar :: Caesar a -> a caesar :: Iso (Caesar a_ad87) (Caesar a_adav) a_ad87 a_adav instance Cipher (ℤ / 26) Caesar instance Monad Caesar instance Applicative Caesar instance Eq a => Eq (Caesar a) instance Show a => Show (Caesar a) instance Functor Caesar module Crypto.Classical.Cipher.Enigma newtype Enigma a Enigma :: a -> Enigma a _enigma :: Enigma a -> a enigma :: Iso (Enigma a_ads8) (Enigma a_aduw) a_ads8 a_aduw -- | When a machine operator presses a key, the Rotors rotate. A circuit is -- then completed as they hold the key down, and a bulb is lit. Here, we -- make sure to rotate the Rotors before encrypting the character. NOTE: -- Decryption is the same as encryption. -- | Applies the initial Rotor settings as defined in the Key to the Rotors -- themselves. These initial rotations do not trigger the turnover of -- neighbouring Rotors as usual. withInitPositions :: EnigmaKey -> EnigmaKey -- | Turn the (machine's) right-most (left-most in List) Rotor by one -- position. If its turnover value wraps back to 25, then turn the next -- Rotor as well. turn :: [Rotor] -> [Rotor] -- | Rotate a Rotor by n positions. By subtracting 1 from every -- key and value, we perfectly simulate rotation. Example: -- --
-- >>> rotate $ M.fromList [(0,2),(1,0),(2,3),(3,4),(4,1)] -- M.fromList [(4,1),(0,4),(1,2),(2,3),(3,0)] --rotate :: ℤ / 26 -> Map (ℤ / 26) (ℤ / 26) -> Map (ℤ / 26) (ℤ / 26) instance Cipher EnigmaKey Enigma instance Monad Enigma instance Applicative Enigma instance Eq a => Eq (Enigma a) instance Show a => Show (Enigma a) instance Functor Enigma module Crypto.Classical.Cipher.Stream -- | A Cipher with pseudorandom keys as long as the plaintext. Since -- Haskell is lazy, our keys here are actually of infinite length. -- -- If for whatever reason a key of finite length is given to -- encrypt, the ciphertext is cutoff to match the key length. -- Example: -- --
-- >>> encrypt [1,2,3] "ABCDEF" ^. stream -- "BDF" --newtype Stream a Stream :: a -> Stream a _stream :: Stream a -> a stream :: Iso (Stream a_aezf) (Stream a_aeCs) a_aezf a_aeCs instance Cipher [ℤ / 26] Stream instance Monad Stream instance Applicative Stream instance Eq a => Eq (Stream a) instance Show a => Show (Stream a) instance Functor Stream module Crypto.Classical.Cipher.Substitution -- | A Cipher whose key is a (pseudo)random mapping of characters to other -- characters. A character may map to itself. newtype Substitution a Substitution :: a -> Substitution a _substitution :: Substitution a -> a substitution :: Iso (Substitution a_aeWM) (Substitution a_aeZa) a_aeWM a_aeZa instance Cipher (Map Char Char) Substitution instance Monad Substitution instance Applicative Substitution instance Eq a => Eq (Substitution a) instance Show a => Show (Substitution a) instance Functor Substitution module Crypto.Classical.Cipher.Vigenere -- | A Vigenère Cipher is just a Stream Cipher with a finite key, shorter -- than the length of the plaintext. The key is repeated for the entire -- length of the plaintext. newtype Vigenère a Vigenère :: a -> Vigenère a _vigenère :: Vigenère a -> a vigenère :: Iso (Vigenère a_afet) (Vigenère a_afgR) a_afet a_afgR -- | Determine a Vigenère key from a Stream key. Weakness here: key length -- is a factor of the plaintext length. vigKey :: ByteString -> [ℤ / 26] -> [ℤ / 26] instance Cipher [ℤ / 26] Vigenère instance Monad Vigenère instance Applicative Vigenère instance Eq a => Eq (Vigenère a) instance Show a => Show (Vigenère a) instance Functor Vigenère module Crypto.Classical.Letter -- | A Letter is a capital Ascii letter (A-Z) data Letter Letter :: Char -> Letter _char :: Letter -> Char instance Eq Letter instance Show Letter instance Arbitrary Letter module Crypto.Classical.Cipher module Crypto.Classical.Test -- | An encrypted message should decrypt to the original plaintext. cycleT :: (Monad c, Cipher k c) => (c ByteString -> ByteString) -> IO () -- | A message should never encrypt to itself. notSelfT :: (Monad c, Cipher k c) => (c ByteString -> ByteString) -> IO () -- | Run every test on every Cipher. testAll :: IO () instance Arbitrary ByteString module Crypto.Classical