crypto-classical 0.0.3 → 0.1.0
raw patch · 4 files changed
+70/−23 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Crypto.Classical.Cipher.Affine: _affine :: Affine a -> a
- Crypto.Classical.Cipher.Affine: instance Applicative Affine
- Crypto.Classical.Cipher.Affine: instance Cipher (ℤ / 26, ℤ / 26) Affine
- Crypto.Classical.Cipher.Affine: instance Eq a => Eq (Affine a)
- Crypto.Classical.Cipher.Affine: instance Functor Affine
- Crypto.Classical.Cipher.Affine: instance Monad Affine
- Crypto.Classical.Cipher.Affine: instance Show a => Show (Affine a)
- Crypto.Classical.Cipher.Caesar: _caesar :: Caesar a -> a
- Crypto.Classical.Cipher.Caesar: instance Applicative Caesar
- Crypto.Classical.Cipher.Caesar: instance Cipher (ℤ / 26) Caesar
- Crypto.Classical.Cipher.Caesar: instance Eq a => Eq (Caesar a)
- Crypto.Classical.Cipher.Caesar: instance Functor Caesar
- Crypto.Classical.Cipher.Caesar: instance Monad Caesar
- Crypto.Classical.Cipher.Caesar: instance Show a => Show (Caesar a)
- Crypto.Classical.Cipher.Enigma: _enigma :: Enigma a -> a
- Crypto.Classical.Cipher.Enigma: instance Applicative Enigma
- Crypto.Classical.Cipher.Enigma: instance Cipher EnigmaKey Enigma
- Crypto.Classical.Cipher.Enigma: instance Eq a => Eq (Enigma a)
- Crypto.Classical.Cipher.Enigma: instance Functor Enigma
- Crypto.Classical.Cipher.Enigma: instance Monad Enigma
- Crypto.Classical.Cipher.Enigma: instance Show a => Show (Enigma a)
- Crypto.Classical.Cipher.Stream: _stream :: Stream a -> a
- Crypto.Classical.Cipher.Stream: instance Applicative Stream
- Crypto.Classical.Cipher.Stream: instance Cipher [ℤ / 26] Stream
- Crypto.Classical.Cipher.Stream: instance Eq a => Eq (Stream a)
- Crypto.Classical.Cipher.Stream: instance Functor Stream
- Crypto.Classical.Cipher.Stream: instance Monad Stream
- Crypto.Classical.Cipher.Stream: instance Show a => Show (Stream a)
- Crypto.Classical.Cipher.Substitution: _substitution :: Substitution a -> a
- Crypto.Classical.Cipher.Substitution: instance Applicative Substitution
- Crypto.Classical.Cipher.Substitution: instance Cipher (Map Char Char) Substitution
- Crypto.Classical.Cipher.Substitution: instance Eq a => Eq (Substitution a)
- Crypto.Classical.Cipher.Substitution: instance Functor Substitution
- Crypto.Classical.Cipher.Substitution: instance Monad Substitution
- Crypto.Classical.Cipher.Substitution: instance Show a => Show (Substitution a)
- Crypto.Classical.Cipher.Vigenere: _vigenère :: Vigenère a -> a
- Crypto.Classical.Cipher.Vigenere: instance Applicative Vigenère
- Crypto.Classical.Cipher.Vigenere: instance Cipher [ℤ / 26] Vigenère
- Crypto.Classical.Cipher.Vigenere: instance Eq a => Eq (Vigenère a)
- Crypto.Classical.Cipher.Vigenere: instance Functor Vigenère
- Crypto.Classical.Cipher.Vigenere: instance Monad Vigenère
- Crypto.Classical.Cipher.Vigenere: instance Show a => Show (Vigenère a)
- Crypto.Classical.Letter: _char :: Letter -> Char
- Crypto.Classical.Letter: instance Arbitrary Letter
- Crypto.Classical.Letter: instance Eq Letter
- Crypto.Classical.Letter: instance Show Letter
- Crypto.Classical.Shuffle: instance Show a => Show (Tree a)
- Crypto.Classical.Test: instance Arbitrary ByteString
- Crypto.Classical.Types: _circuit :: Rotor -> Map (ℤ / 26) (ℤ / 26)
- Crypto.Classical.Types: _name :: Rotor -> Text
- Crypto.Classical.Types: _plugboard :: EnigmaKey -> Plugboard
- Crypto.Classical.Types: _reflector :: EnigmaKey -> Reflector
- Crypto.Classical.Types: _rotors :: EnigmaKey -> [Rotor]
- Crypto.Classical.Types: _settings :: EnigmaKey -> [Char]
- Crypto.Classical.Types: _turnover :: Rotor -> ℤ / 26
- Crypto.Classical.Types: instance Eq EnigmaKey
- Crypto.Classical.Types: instance Eq Rotor
- Crypto.Classical.Types: instance Key (Map Char Char)
- Crypto.Classical.Types: instance Key (ℤ / 26)
- Crypto.Classical.Types: instance Key (ℤ / 26, ℤ / 26)
- Crypto.Classical.Types: instance Key EnigmaKey
- Crypto.Classical.Types: instance Key [ℤ / 26]
- Crypto.Classical.Types: instance Show EnigmaKey
- Crypto.Classical.Types: instance Show Rotor
+ Crypto.Classical.Cipher.Affine: [_affine] :: Affine a -> a
+ Crypto.Classical.Cipher.Affine: instance Crypto.Classical.Types.Cipher (Data.Modular.ℤ Data.Modular./ 26, Data.Modular.ℤ Data.Modular./ 26) Crypto.Classical.Cipher.Affine.Affine
+ Crypto.Classical.Cipher.Affine: instance GHC.Base.Applicative Crypto.Classical.Cipher.Affine.Affine
+ Crypto.Classical.Cipher.Affine: instance GHC.Base.Functor Crypto.Classical.Cipher.Affine.Affine
+ Crypto.Classical.Cipher.Affine: instance GHC.Base.Monad Crypto.Classical.Cipher.Affine.Affine
+ Crypto.Classical.Cipher.Affine: instance GHC.Classes.Eq a => GHC.Classes.Eq (Crypto.Classical.Cipher.Affine.Affine a)
+ Crypto.Classical.Cipher.Affine: instance GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Cipher.Affine.Affine a)
+ Crypto.Classical.Cipher.Caesar: [_caesar] :: Caesar a -> a
+ Crypto.Classical.Cipher.Caesar: instance Crypto.Classical.Types.Cipher (Data.Modular.ℤ Data.Modular./ 26) Crypto.Classical.Cipher.Caesar.Caesar
+ Crypto.Classical.Cipher.Caesar: instance GHC.Base.Applicative Crypto.Classical.Cipher.Caesar.Caesar
+ Crypto.Classical.Cipher.Caesar: instance GHC.Base.Functor Crypto.Classical.Cipher.Caesar.Caesar
+ Crypto.Classical.Cipher.Caesar: instance GHC.Base.Monad Crypto.Classical.Cipher.Caesar.Caesar
+ Crypto.Classical.Cipher.Caesar: instance GHC.Classes.Eq a => GHC.Classes.Eq (Crypto.Classical.Cipher.Caesar.Caesar a)
+ Crypto.Classical.Cipher.Caesar: instance GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Cipher.Caesar.Caesar a)
+ Crypto.Classical.Cipher.Enigma: [_enigma] :: Enigma a -> a
+ Crypto.Classical.Cipher.Enigma: instance Crypto.Classical.Types.Cipher Crypto.Classical.Types.EnigmaKey Crypto.Classical.Cipher.Enigma.Enigma
+ Crypto.Classical.Cipher.Enigma: instance GHC.Base.Applicative Crypto.Classical.Cipher.Enigma.Enigma
+ Crypto.Classical.Cipher.Enigma: instance GHC.Base.Functor Crypto.Classical.Cipher.Enigma.Enigma
+ Crypto.Classical.Cipher.Enigma: instance GHC.Base.Monad Crypto.Classical.Cipher.Enigma.Enigma
+ Crypto.Classical.Cipher.Enigma: instance GHC.Classes.Eq a => GHC.Classes.Eq (Crypto.Classical.Cipher.Enigma.Enigma a)
+ Crypto.Classical.Cipher.Enigma: instance GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Cipher.Enigma.Enigma a)
+ Crypto.Classical.Cipher.Stream: [_stream] :: Stream a -> a
+ Crypto.Classical.Cipher.Stream: instance Crypto.Classical.Types.Cipher [Data.Modular.ℤ Data.Modular./ 26] Crypto.Classical.Cipher.Stream.Stream
+ Crypto.Classical.Cipher.Stream: instance GHC.Base.Applicative Crypto.Classical.Cipher.Stream.Stream
+ Crypto.Classical.Cipher.Stream: instance GHC.Base.Functor Crypto.Classical.Cipher.Stream.Stream
+ Crypto.Classical.Cipher.Stream: instance GHC.Base.Monad Crypto.Classical.Cipher.Stream.Stream
+ Crypto.Classical.Cipher.Stream: instance GHC.Classes.Eq a => GHC.Classes.Eq (Crypto.Classical.Cipher.Stream.Stream a)
+ Crypto.Classical.Cipher.Stream: instance GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Cipher.Stream.Stream a)
+ Crypto.Classical.Cipher.Substitution: [_substitution] :: Substitution a -> a
+ Crypto.Classical.Cipher.Substitution: instance Crypto.Classical.Types.Cipher (Data.Map.Base.Map GHC.Types.Char GHC.Types.Char) Crypto.Classical.Cipher.Substitution.Substitution
+ Crypto.Classical.Cipher.Substitution: instance GHC.Base.Applicative Crypto.Classical.Cipher.Substitution.Substitution
+ Crypto.Classical.Cipher.Substitution: instance GHC.Base.Functor Crypto.Classical.Cipher.Substitution.Substitution
+ Crypto.Classical.Cipher.Substitution: instance GHC.Base.Monad Crypto.Classical.Cipher.Substitution.Substitution
+ Crypto.Classical.Cipher.Substitution: instance GHC.Classes.Eq a => GHC.Classes.Eq (Crypto.Classical.Cipher.Substitution.Substitution a)
+ Crypto.Classical.Cipher.Substitution: instance GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Cipher.Substitution.Substitution a)
+ Crypto.Classical.Cipher.Vigenere: [_vigenère] :: Vigenère a -> a
+ Crypto.Classical.Cipher.Vigenere: instance Crypto.Classical.Types.Cipher [Data.Modular.ℤ Data.Modular./ 26] Crypto.Classical.Cipher.Vigenere.Vigenère
+ Crypto.Classical.Cipher.Vigenere: instance GHC.Base.Applicative Crypto.Classical.Cipher.Vigenere.Vigenère
+ Crypto.Classical.Cipher.Vigenere: instance GHC.Base.Functor Crypto.Classical.Cipher.Vigenere.Vigenère
+ Crypto.Classical.Cipher.Vigenere: instance GHC.Base.Monad Crypto.Classical.Cipher.Vigenere.Vigenère
+ Crypto.Classical.Cipher.Vigenere: instance GHC.Classes.Eq a => GHC.Classes.Eq (Crypto.Classical.Cipher.Vigenere.Vigenère a)
+ Crypto.Classical.Cipher.Vigenere: instance GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Cipher.Vigenere.Vigenère a)
+ Crypto.Classical.Letter: [_char] :: Letter -> Char
+ Crypto.Classical.Letter: instance GHC.Classes.Eq Crypto.Classical.Letter.Letter
+ Crypto.Classical.Letter: instance GHC.Show.Show Crypto.Classical.Letter.Letter
+ Crypto.Classical.Letter: instance Test.QuickCheck.Arbitrary.Arbitrary Crypto.Classical.Letter.Letter
+ Crypto.Classical.Shuffle: instance GHC.Show.Show a => GHC.Show.Show (Crypto.Classical.Shuffle.Tree a)
+ Crypto.Classical.Test: diffKeyT :: (Eq k, Monad c, Cipher k c) => (c ByteString -> ByteString) -> IO ()
+ Crypto.Classical.Test: instance Test.QuickCheck.Arbitrary.Arbitrary Data.ByteString.Lazy.Internal.ByteString
+ Crypto.Classical.Test: noSelfMappingT :: IO ()
+ Crypto.Classical.Test: plugFromT :: IO ()
+ Crypto.Classical.Test: stretchT :: IO ()
+ Crypto.Classical.Types: [_circuit] :: Rotor -> Map (ℤ / 26) (ℤ / 26)
+ Crypto.Classical.Types: [_name] :: Rotor -> Text
+ Crypto.Classical.Types: [_plugboard] :: EnigmaKey -> Plugboard
+ Crypto.Classical.Types: [_reflector] :: EnigmaKey -> Reflector
+ Crypto.Classical.Types: [_rotors] :: EnigmaKey -> [Rotor]
+ Crypto.Classical.Types: [_settings] :: EnigmaKey -> [Char]
+ Crypto.Classical.Types: [_turnover] :: Rotor -> ℤ / 26
+ Crypto.Classical.Types: instance Crypto.Classical.Types.Key (Data.Map.Base.Map GHC.Types.Char GHC.Types.Char)
+ Crypto.Classical.Types: instance Crypto.Classical.Types.Key (Data.Modular.ℤ Data.Modular./ 26)
+ Crypto.Classical.Types: instance Crypto.Classical.Types.Key (Data.Modular.ℤ Data.Modular./ 26, Data.Modular.ℤ Data.Modular./ 26)
+ Crypto.Classical.Types: instance Crypto.Classical.Types.Key Crypto.Classical.Types.EnigmaKey
+ Crypto.Classical.Types: instance Crypto.Classical.Types.Key [Data.Modular.ℤ Data.Modular./ 26]
+ Crypto.Classical.Types: instance GHC.Classes.Eq Crypto.Classical.Types.EnigmaKey
+ Crypto.Classical.Types: instance GHC.Classes.Eq Crypto.Classical.Types.Rotor
+ Crypto.Classical.Types: instance GHC.Show.Show Crypto.Classical.Types.EnigmaKey
+ Crypto.Classical.Types: instance GHC.Show.Show Crypto.Classical.Types.Rotor
+ Crypto.Classical.Types: plugFrom :: [(Char, Char)] -> Plugboard
+ Crypto.Classical.Util: stretch :: [a] -> [a]
- Crypto.Classical.Cipher.Affine: affine :: Iso (Affine a_acIg) (Affine a_acLQ) a_acIg a_acLQ
+ Crypto.Classical.Cipher.Affine: affine :: Iso (Affine a_afrg) (Affine a_afub) a_afrg a_afub
- Crypto.Classical.Cipher.Caesar: caesar :: Iso (Caesar a_ad87) (Caesar a_adav) a_ad87 a_adav
+ Crypto.Classical.Cipher.Caesar: caesar :: Iso (Caesar a_afRT) (Caesar a_afUj) a_afRT a_afUj
- Crypto.Classical.Cipher.Enigma: enigma :: Iso (Enigma a_ads8) (Enigma a_aduw) a_ads8 a_aduw
+ Crypto.Classical.Cipher.Enigma: enigma :: Iso (Enigma a_aged) (Enigma a_aggF) a_aged a_aggF
- Crypto.Classical.Cipher.Stream: stream :: Iso (Stream a_aezf) (Stream a_aeCs) a_aezf a_aeCs
+ Crypto.Classical.Cipher.Stream: stream :: Iso (Stream a_ai2D) (Stream a_ai6P) a_ai2D a_ai6P
- Crypto.Classical.Cipher.Substitution: substitution :: Iso (Substitution a_aeWM) (Substitution a_aeZa) a_aeWM a_aeZa
+ Crypto.Classical.Cipher.Substitution: substitution :: Iso (Substitution a_airH) (Substitution a_aiu7) a_airH a_aiu7
- Crypto.Classical.Cipher.Vigenere: vigenère :: Iso (Vigenère a_afet) (Vigenère a_afgR) a_afet a_afgR
+ Crypto.Classical.Cipher.Vigenere: vigenère :: Iso (Vigenère a_aiJO) (Vigenère a_aiMe) a_aiJO a_aiMe
Files
- Crypto/Classical/Test.hs +47/−22
- Crypto/Classical/Types.hs +12/−0
- Crypto/Classical/Util.hs +10/−0
- crypto-classical.cabal +1/−1
Crypto/Classical/Test.hs view
@@ -9,9 +9,14 @@ module Crypto.Classical.Test (- -- * Single Tests+ -- * Cipher Tests cycleT , notSelfT+ , diffKeyT+ , noSelfMappingT+ -- * Misc. Tests+ , stretchT+ , plugFromT -- * Batch Tests , testAll ) where@@ -22,9 +27,10 @@ import Crypto.Classical.Cipher import Crypto.Classical.Letter import Crypto.Classical.Types-import Crypto.Classical.Util (prng)+import Crypto.Classical.Util import Data.ByteString.Lazy.Char8 (ByteString) import qualified Data.ByteString.Lazy.Char8 as B+import qualified Data.Foldable as F import Test.QuickCheck ---@@ -38,27 +44,33 @@ -- | Run every test on every Cipher. testAll :: IO ()-testAll = void $ sequence [ cycleT $ view caesar- , cycleT $ view affine- , cycleT $ view substitution- , cycleT $ view stream- , cycleT $ view vigenère- , cycleT $ view enigma- , notSelfT $ view caesar- , notSelfT $ view affine- , notSelfT $ view substitution- , notSelfT $ view stream- , notSelfT $ view vigenère- , notSelfT $ view enigma- , diffKeyT $ view caesar- , diffKeyT $ view affine- , diffKeyT $ view substitution- , diffKeyT $ view stream- , diffKeyT $ view vigenère- , diffKeyT $ view enigma- , noSelfMappingT- ]+testAll = void . sequence $ cipherTs ++ otherTs +cipherTs :: [IO ()]+cipherTs = [ cycleT $ view caesar+ , cycleT $ view affine+ , cycleT $ view substitution+ , cycleT $ view stream+ , cycleT $ view vigenère+ , cycleT $ view enigma+ , notSelfT $ view caesar+ , notSelfT $ view affine+ , notSelfT $ view substitution+ , notSelfT $ view stream+ , notSelfT $ view vigenère+ , notSelfT $ view enigma+ , diffKeyT $ view caesar+ , diffKeyT $ view affine+ , diffKeyT $ view substitution+ , diffKeyT $ view stream+ , diffKeyT $ view vigenère+ , diffKeyT $ view enigma+ , noSelfMappingT+ ]++otherTs :: [IO ()]+otherTs = [ stretchT, plugFromT ]+ -- | An encrypted message should decrypt to the original plaintext. cycleT :: (Monad c, Cipher k c) => (c ByteString -> ByteString) -> IO () cycleT f = do@@ -93,3 +105,16 @@ enig = do k <- key <$> prng return $ encrypt k "Das ist ein Wetterbericht. Heil Hitler." ^. enigma++-- | A stretch should always double the length.+stretchT :: IO ()+stretchT = quickCheck prop+ where prop :: [Int] -> Property+ prop xs = let l = length xs in l > 0 ==> length (stretch xs) == 2 * l++-- | Any list of pairs should always result in a Plugboard of 26 mappings.+plugFromT :: IO ()+plugFromT = quickCheck prop+ where prop :: [(Letter,Letter)] -> Bool+ prop xs = let xs' = xs & traverse . both %~ _char in+ F.length (plugFrom xs') == 26
Crypto/Classical/Types.hs view
@@ -31,6 +31,7 @@ , settings , reflector , plugboard+ , plugFrom ) where import Control.Lens@@ -39,6 +40,7 @@ import Crypto.Number.Generate import Crypto.Random (CPRG) import Data.ByteString.Lazy (ByteString)+import Data.Char (isUpper) import Data.List ((\\)) import Data.Map.Lazy (Map) import qualified Data.Map.Lazy as M@@ -178,3 +180,13 @@ (ps,ss) = (take 20 shuffled, drop 20 shuffled) pairs = foldr (\(k,v) acc -> (k,v) : (v,k) : acc) [] $ uniZip ps singles = foldr (\v acc -> (v,v) : acc) [] ss++-- | Given a list of letter pairs, generates a Plugboard.+-- Any letters left out of the pair list will be mapped to themselves.+plugFrom :: [(Char,Char)] -> Plugboard+plugFrom = f []+ where f acc [] = let rest = stretch (['A'..'Z'] \\ acc) in+ M.fromList . uniZip . map int $ acc ++ rest+ f acc ((a,b):ps) | a `notElem` acc && b `notElem` acc &&+ isUpper a && isUpper b = f (a : b : b : a : acc) ps+ | otherwise = f acc ps
Crypto/Classical/Util.hs view
@@ -23,6 +23,7 @@ , (|.|) -- * Miscellaneous , uniZip+ , stretch ) where import Control.Lens@@ -88,3 +89,12 @@ uniZip [] = [] uniZip [_] = [] uniZip (a:b:xs) = (a,b) : uniZip xs++-- | Stretch the contents of a list. List becomes twice a long.+-- List must be finite.+-- Example:+--+-- >>> stretch [1,2,3,4]+-- [1,1,2,2,3,3,4,4]+stretch :: [a] -> [a]+stretch = foldr (\x acc -> x : x : acc) []
crypto-classical.cabal view
@@ -1,6 +1,6 @@ name: crypto-classical -version: 0.0.3+version: 0.1.0 synopsis: An educational tool for studying classical cryptography schemes.