-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | An educational tool for studying classical cryptography schemes. -- -- An educational tool for studying classical cryptography schemes. Do -- not encrypt anything of worth with this library. -- -- Included Ciphers: -- --
-- > import Crypto.Classical -- > import Control.Lens -- > :set -XOverloadedStrings -- > (key <$> prng) >>= \k -> return (encrypt k "What a great day for an attack!" ^. enigma) -- "PXQS D KXSGB CFC AYK XJ DEGMON!" -- > (key <$> prng) >>= \k -> return (encrypt k "What a great day for an attack!" ^. caesar) -- "RCVO V BMZVO YVT AJM VI VOOVXF!" --@package crypto-classical @version 0.0.2 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 GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Shuffle.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 -- | Randomly generate a Key. 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 Crypto.Classical.Types.Key Crypto.Classical.Types.EnigmaKey instance GHC.Show.Show Crypto.Classical.Types.EnigmaKey instance GHC.Classes.Eq Crypto.Classical.Types.EnigmaKey instance GHC.Show.Show Crypto.Classical.Types.Rotor instance GHC.Classes.Eq Crypto.Classical.Types.Rotor instance Crypto.Classical.Types.Key (Data.Modular.ℤ Data.Modular./ 26) instance Crypto.Classical.Types.Key (Data.Modular.ℤ Data.Modular./ 26, Data.Modular.ℤ Data.Modular./ 26) instance Crypto.Classical.Types.Key (Data.Map.Base.Map GHC.Types.Char GHC.Types.Char) instance Crypto.Classical.Types.Key [Data.Modular.ℤ Data.Modular./ 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_afj7) (Affine a_afm2) a_afj7 a_afm2 instance GHC.Base.Applicative Crypto.Classical.Cipher.Affine.Affine instance GHC.Base.Monad Crypto.Classical.Cipher.Affine.Affine instance Crypto.Classical.Types.Cipher (Data.Modular.ℤ Data.Modular./ 26, Data.Modular.ℤ Data.Modular./ 26) Crypto.Classical.Cipher.Affine.Affine instance GHC.Base.Functor Crypto.Classical.Cipher.Affine.Affine instance GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Cipher.Affine.Affine a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Crypto.Classical.Cipher.Affine.Affine a) 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_afK4) (Caesar a_afMu) a_afK4 a_afMu instance GHC.Base.Applicative Crypto.Classical.Cipher.Caesar.Caesar instance GHC.Base.Monad Crypto.Classical.Cipher.Caesar.Caesar instance Crypto.Classical.Types.Cipher (Data.Modular.ℤ Data.Modular./ 26) Crypto.Classical.Cipher.Caesar.Caesar instance GHC.Base.Functor Crypto.Classical.Cipher.Caesar.Caesar instance GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Cipher.Caesar.Caesar a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Crypto.Classical.Cipher.Caesar.Caesar a) module Crypto.Classical.Cipher.Enigma newtype Enigma a Enigma :: a -> Enigma a [_enigma] :: Enigma a -> a enigma :: Iso (Enigma a_ag6o) (Enigma a_ag8Q) a_ag6o a_ag8Q -- | 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 GHC.Base.Applicative Crypto.Classical.Cipher.Enigma.Enigma instance GHC.Base.Monad Crypto.Classical.Cipher.Enigma.Enigma instance Crypto.Classical.Types.Cipher Crypto.Classical.Types.EnigmaKey Crypto.Classical.Cipher.Enigma.Enigma instance GHC.Base.Functor Crypto.Classical.Cipher.Enigma.Enigma instance GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Cipher.Enigma.Enigma a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Crypto.Classical.Cipher.Enigma.Enigma a) 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_ahUO) (Stream a_ahZ0) a_ahUO a_ahZ0 instance GHC.Base.Applicative Crypto.Classical.Cipher.Stream.Stream instance GHC.Base.Monad Crypto.Classical.Cipher.Stream.Stream instance Crypto.Classical.Types.Cipher [Data.Modular.ℤ Data.Modular./ 26] Crypto.Classical.Cipher.Stream.Stream instance GHC.Base.Functor Crypto.Classical.Cipher.Stream.Stream instance GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Cipher.Stream.Stream a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Crypto.Classical.Cipher.Stream.Stream a) 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_aijS) (Substitution a_aimi) a_aijS a_aimi instance GHC.Base.Applicative Crypto.Classical.Cipher.Substitution.Substitution instance GHC.Base.Monad Crypto.Classical.Cipher.Substitution.Substitution instance Crypto.Classical.Types.Cipher (Data.Map.Base.Map GHC.Types.Char GHC.Types.Char) Crypto.Classical.Cipher.Substitution.Substitution instance GHC.Base.Functor Crypto.Classical.Cipher.Substitution.Substitution instance GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Cipher.Substitution.Substitution a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Crypto.Classical.Cipher.Substitution.Substitution a) 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_aiBZ) (Vigenère a_aiEp) a_aiBZ a_aiEp -- | 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 GHC.Base.Applicative Crypto.Classical.Cipher.Vigenere.Vigenère instance GHC.Base.Monad Crypto.Classical.Cipher.Vigenere.Vigenère instance Crypto.Classical.Types.Cipher [Data.Modular.ℤ Data.Modular./ 26] Crypto.Classical.Cipher.Vigenere.Vigenère instance GHC.Base.Functor Crypto.Classical.Cipher.Vigenere.Vigenère instance GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Cipher.Vigenere.Vigenère a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Crypto.Classical.Cipher.Vigenere.Vigenère a) module Crypto.Classical.Letter -- | A Letter is a capital Ascii letter (A-Z) data Letter Letter :: Char -> Letter [_char] :: Letter -> Char instance GHC.Show.Show Crypto.Classical.Letter.Letter instance GHC.Classes.Eq Crypto.Classical.Letter.Letter instance Test.QuickCheck.Arbitrary.Arbitrary Crypto.Classical.Letter.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 Test.QuickCheck.Arbitrary.Arbitrary Data.ByteString.Lazy.Internal.ByteString module Crypto.Classical