module Data.Cipher
(
Cipher
,MonadCbc
,Cbc
,CbcT
,encrypt
,decrypt
,evalCbc
,evalCbcT
,cbcEncrypt
,cbcDecrypt
) where
import Control.Monad.State
import Data.Bits
newtype Cbc c iv a = Cbc (State (c, iv) a)
deriving (Monad, Functor)
newtype CbcT c iv m a = CbcT (StateT (c, iv) m a)
deriving (Monad, Functor, MonadTrans)
evalCbc :: Cbc c w a -> c -> w -> a
evalCbc (Cbc s) c iv = evalState s (c, iv)
evalCbcT :: (Monad m) => CbcT c w m a -> c -> w -> m a
evalCbcT (CbcT s) c iv = evalStateT s (c, iv)
class (Bits w) => Cipher w c | c -> w where
encrypt :: c -> w -> w
decrypt :: c -> w -> w
class (Bits w, Cipher w c, MonadState (c, w) s) => MonadCbc c w s m | m -> c, m -> w, m -> s where
monadCbc :: s w -> m w
instance (Bits w, Cipher w c) => MonadCbc c w (State (c, w)) (Cbc c w) where
monadCbc = Cbc
instance (Bits w, Cipher w c, Monad m) => MonadCbc c w (StateT (c, w) m) (CbcT c w m) where
monadCbc = CbcT
cbcEncrypt :: (MonadCbc c w s m) => w -> m w
cbcEncrypt w = monadCbc $ do (c, iv) <- get
let w' = encrypt c (w `xor` iv)
put (c, w')
return w'
cbcDecrypt :: (MonadCbc c w s m) => w -> m w
cbcDecrypt w = monadCbc $ do (c, iv) <- get
let w' = (decrypt c w) `xor` iv
put (c, w)
return w'