{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeOperators #-} -- | -- Module : Crypto.Classical.Stream -- Copyright : (c) Colin Woodbury, 2015 - 2020 -- License : BSD3 -- Maintainer: Colin Woodbury module Crypto.Classical.Cipher.Stream where import Crypto.Classical.Types import Crypto.Classical.Util import qualified Data.ByteString.Lazy.Char8 as B import Data.Char import Data.Modular --- -- | 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: -- -- >>> _stream $ encrypt [1,2,3] "ABCDEF" -- "BDF" newtype Stream a = Stream { _stream :: a } deriving (Eq,Show,Functor) instance Applicative Stream where pure = Stream Stream f <*> Stream a = Stream $ f a instance Monad Stream where return = pure Stream a >>= f = f a instance Cipher [ℤ/26] Stream where encrypt k = pure . B.pack . f k . B.unpack where f _ [] = [] f [] _ = [] f (kc:ks) (m:ms) | isLower m = f (kc:ks) (toUpper m : ms) | not $ isLetter m = m : f ks ms | otherwise = letter (int m + kc) : f ks ms decrypt k = encrypt k' where k' = map (* (-1)) k