packages feed

crypto-cipher-types 0.0.7 → 0.0.8

raw patch · 10 files changed

+847/−329 lines, 10 filesdep ~base

Dependency ranges changed: base

Files

Crypto/Cipher/Types.hs view
@@ -8,8 +8,6 @@ -- symmetric cipher basic types -- {-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ExistentialQuantification #-} module Crypto.Cipher.Types     (     -- * Cipher classes@@ -23,16 +21,10 @@     , AEADState(..)     , AEADMode(..)     , AEADModeImpl(..)-    -- * CFB8 mode     , cfb8Encrypt     , cfb8Decrypt-    -- * AEAD-    , aeadAppendHeader-    , aeadEncrypt-    , aeadDecrypt-    , aeadFinalize-    , aeadSimpleEncrypt-    , aeadSimpleDecrypt+    -- * AEAD functions+    , module Crypto.Cipher.Types.AEAD     -- * Key type and constructor     , Key     , makeKey@@ -46,229 +38,11 @@     ) where  import Data.SecureMem-import Data.ByteString (ByteString)-import qualified Data.ByteString as B-import qualified Data.ByteString.Internal as B (unsafeCreate) import Data.Byteable-import Data.Word-import Data.Bits (shiftR, xor)-import Crypto.Cipher.Types.GF-import Foreign.Storable (poke)-import Foreign.Ptr (plusPtr)---- | Offset inside an XTS data unit, measured in block size.-type DataUnitOffset = Word32---- | Possible Error that can be reported when initializating a key-data KeyError =-      KeyErrorTooSmall-    | KeyErrorTooBig-    | KeyErrorInvalid String-    deriving (Show,Eq)---- | Different specifier for key size in bytes-data KeySizeSpecifier =-      KeySizeRange Int Int -- ^ in the range [min,max]-    | KeySizeEnum  [Int]   -- ^ one of the specified values-    | KeySizeFixed Int     -- ^ a specific size-    deriving (Show,Eq)---- | Symmetric cipher class.-class Cipher cipher where-    -- | Initialize a cipher context from a key-    cipherInit    :: Key cipher -> cipher-    -- | Cipher name-    cipherName    :: cipher -> String-    -- | return the size of the key required for this cipher.-    -- Some cipher accept any size for key-    cipherKeySize :: cipher -> KeySizeSpecifier---- | Symmetric stream cipher class-class Cipher cipher => StreamCipher cipher where-    -- | Combine using the stream cipher-    streamCombine :: cipher -> ByteString -> (ByteString, cipher)---- | Symmetric block cipher class-class Cipher cipher => BlockCipher cipher where-    -- | Return the size of block required for this block cipher-    blockSize    :: cipher -> Int--    -- | Encrypt using the ECB mode.-    ---    -- input need to be a multiple of the blocksize-    ecbEncrypt :: cipher -> ByteString -> ByteString-    -- | Decrypt using the ECB mode.-    ---    -- input need to be a multiple of the blocksize-    ecbDecrypt :: cipher -> ByteString -> ByteString--    -- | encrypt using the CBC mode.-    ---    -- input need to be a multiple of the blocksize-    cbcEncrypt :: cipher -> IV cipher -> ByteString -> ByteString-    cbcEncrypt = cbcEncryptGeneric-    -- | decrypt using the CBC mode.-    ---    -- input need to be a multiple of the blocksize-    cbcDecrypt :: cipher -> IV cipher -> ByteString -> ByteString-    cbcDecrypt = cbcDecryptGeneric--    -- | encrypt using the CFB mode.-    ---    -- input need to be a multiple of the blocksize-    cfbEncrypt :: cipher -> IV cipher -> ByteString -> ByteString-    cfbEncrypt = cfbEncryptGeneric-    -- | decrypt using the CFB mode.-    ---    -- input need to be a multiple of the blocksize-    cfbDecrypt :: cipher -> IV cipher -> ByteString -> ByteString-    cfbDecrypt = cfbDecryptGeneric--    -- | combine using the CTR mode.-    ---    -- CTR mode produce a stream of randomized data that is combined-    -- (by XOR operation) with the input stream.-    ---    -- encryption and decryption are the same operation.-    ---    -- input can be of any size-    ctrCombine :: cipher -> IV cipher -> ByteString -> ByteString-    ctrCombine = ctrCombineGeneric--    -- | encrypt using the XTS mode.-    ---    -- input need to be a multiple of the blocksize-    xtsEncrypt :: (cipher, cipher) -> IV cipher -> DataUnitOffset -> ByteString -> ByteString-    xtsEncrypt = xtsEncryptGeneric-    -- | decrypt using the XTS mode.-    ---    -- input need to be a multiple of the blocksize-    xtsDecrypt :: (cipher, cipher) -> IV cipher -> DataUnitOffset -> ByteString -> ByteString-    xtsDecrypt = xtsDecryptGeneric--    -- | Initialize a new AEAD State-    ---    -- When Nothing is returns, it means the mode is not handled.-    aeadInit :: Byteable iv => AEADMode -> cipher -> iv -> Maybe (AEAD cipher)-    aeadInit _ _ _ = Nothing---- | AEAD Mode-data AEADMode =-      AEAD_OCB-    | AEAD_CCM-    | AEAD_EAX-    | AEAD_CWC-    | AEAD_GCM-    deriving (Show,Eq)---- | Authenticated Encryption with Associated Data algorithms-data AEAD cipher = AEAD cipher (AEADState cipher)---- | Wrapper for any AEADState-data AEADState cipher = forall st . AEADModeImpl cipher st => AEADState st---- | Class of AEAD Mode implementation-class BlockCipher cipher => AEADModeImpl cipher state where-    aeadStateAppendHeader :: cipher -> state -> ByteString -> state-    aeadStateEncrypt      :: cipher -> state -> ByteString -> (ByteString, state)-    aeadStateDecrypt      :: cipher -> state -> ByteString -> (ByteString, state)-    aeadStateFinalize     :: cipher -> state -> Int -> AuthTag---- | Append associated data into the AEAD state-aeadAppendHeader :: BlockCipher a => AEAD a -> ByteString -> AEAD a-aeadAppendHeader (AEAD cipher (AEADState state)) bs =-    AEAD cipher $ AEADState (aeadStateAppendHeader cipher state bs)---- | Encrypt input and append into the AEAD state-aeadEncrypt :: BlockCipher a => AEAD a -> ByteString -> (ByteString, AEAD a)-aeadEncrypt (AEAD cipher (AEADState state)) input = (output, AEAD cipher (AEADState nst))-  where (output, nst) = aeadStateEncrypt cipher state input---- | Decrypt input and append into the AEAD state-aeadDecrypt :: BlockCipher a => AEAD a -> ByteString -> (ByteString, AEAD a)-aeadDecrypt (AEAD cipher (AEADState state)) input = (output, AEAD cipher (AEADState nst))-  where (output, nst) = aeadStateDecrypt cipher state input---- | Finalize the AEAD state and create an authentification tag-aeadFinalize :: BlockCipher a => AEAD a -> Int -> AuthTag-aeadFinalize (AEAD cipher (AEADState state)) len =-    aeadStateFinalize cipher state len---- | Simple AEAD encryption-aeadSimpleEncrypt :: BlockCipher a-                  => AEAD a        -- ^ A new AEAD Context-                  -> B.ByteString  -- ^ Optional Authentified Header-                  -> B.ByteString  -- ^ Optional Plaintext-                  -> Int           -- ^ Tag length-                  -> (AuthTag, B.ByteString) -- ^ Authentification tag and ciphertext-aeadSimpleEncrypt aeadIni header input taglen = (tag, output)-  where aead                = aeadAppendHeader aeadIni header-        (output, aeadFinal) = aeadEncrypt aead input-        tag                 = aeadFinalize aeadFinal taglen---- | Simple AEAD decryption-aeadSimpleDecrypt :: BlockCipher a-                  => AEAD a        -- ^ A new AEAD Context-                  -> B.ByteString  -- ^ Optional Authentified Header-                  -> B.ByteString  -- ^ Optional Plaintext-                  -> AuthTag       -- ^ Tag length-                  -> Maybe B.ByteString -- ^ Plaintext-aeadSimpleDecrypt aeadIni header input authTag-    | tag == authTag = Just output-    | otherwise      = Nothing-  where aead                = aeadAppendHeader aeadIni header-        (output, aeadFinal) = aeadDecrypt aead input-        tag                 = aeadFinalize aeadFinal (byteableLength authTag)---- | a Key parametrized by the cipher-newtype Key c = Key SecureMem deriving (Eq)--instance ToSecureMem (Key c) where-    toSecureMem (Key sm) = sm-instance Byteable (Key c) where-    toBytes (Key sm) = toBytes sm---- | an IV parametrized by the cipher-newtype IV c = IV ByteString deriving (Eq)--instance Byteable (IV c) where-    toBytes (IV sm) = sm---- | Authentification Tag for AE cipher mode-newtype AuthTag = AuthTag ByteString-    deriving (Show)--instance Eq AuthTag where-    (AuthTag a) == (AuthTag b) = constEqBytes a b-instance Byteable AuthTag where-    toBytes (AuthTag bs) = bs---- | Create an IV for a specified block cipher-makeIV :: (Byteable b, BlockCipher c) => b -> Maybe (IV c)-makeIV b = toIV undefined-  where toIV :: BlockCipher c => c -> Maybe (IV c)-        toIV cipher-          | byteableLength b == sz = Just (IV $ toBytes b)-          | otherwise              = Nothing-          where sz = blockSize cipher---- | Create an IV that is effectively representing the number 0-nullIV :: BlockCipher c => IV c-nullIV = toIV undefined-  where toIV :: BlockCipher c => c -> IV c-        toIV cipher = IV $ B.replicate (blockSize cipher) 0---- | Increment an IV by a number.------ Assume the IV is in Big Endian format.-ivAdd :: BlockCipher c => IV c -> Int -> IV c-ivAdd (IV b) i = IV $ snd $ B.mapAccumR addCarry i b-  where addCarry :: Int -> Word8 -> (Int, Word8)-        addCarry acc w-            | acc == 0  = (0, w)-            | otherwise = let (hi,lo) = acc `divMod` 256-                              nw      = lo + (fromIntegral w)-                           in (hi + (nw `shiftR` 8), fromIntegral nw)+import Crypto.Cipher.Types.Base+import Crypto.Cipher.Types.Block+import Crypto.Cipher.Types.Stream+import Crypto.Cipher.Types.AEAD  -- | Create a Key for a specified cipher makeKey :: (ToSecureMem b, Cipher c) => b -> Either KeyError (Key c)@@ -284,99 +58,3 @@                           | otherwise       -> Left $ KeyErrorInvalid ("valid size: " ++ show l)             KeySizeFixed v | smLen == v     -> Right $ Key sm                            | otherwise      -> Left $ KeyErrorInvalid ("valid size: " ++ show v)--cbcEncryptGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString-cbcEncryptGeneric cipher (IV ivini) input = B.concat $ doEnc ivini $ chunk (blockSize cipher) input-  where doEnc _  []     = []-        doEnc iv (i:is) =-            let o = ecbEncrypt cipher $ bxor iv i-             in o : doEnc o is--cbcDecryptGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString-cbcDecryptGeneric cipher (IV ivini) input = B.concat $ doDec ivini $ chunk (blockSize cipher) input-  where doDec _  []     = []-        doDec iv (i:is) =-            let o = bxor iv $ ecbDecrypt cipher i-             in o : doDec i is--cfbEncryptGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString-cfbEncryptGeneric cipher (IV ivini) input = B.concat $ doEnc ivini $ chunk (blockSize cipher) input-  where doEnc _  []     = []-        doEnc iv (i:is) =-            let o = bxor i $ ecbEncrypt cipher iv-             in o : doEnc o is--cfbDecryptGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString-cfbDecryptGeneric cipher (IV ivini) input = B.concat $ doDec ivini $ chunk (blockSize cipher) input-  where doDec _  []     = []-        doDec iv (i:is) =-            let o = bxor i $ ecbEncrypt cipher iv-             in o : doDec i is--ctrCombineGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString-ctrCombineGeneric cipher ivini input = B.concat $ doCnt ivini $ chunk (blockSize cipher) input-  where doCnt _  [] = []-        doCnt iv (i:is) =-            let ivEnc = ecbEncrypt cipher (toBytes iv)-             in bxor i ivEnc : doCnt (ivAdd iv 1) is--xtsEncryptGeneric :: BlockCipher cipher => (cipher,cipher) -> IV cipher -> DataUnitOffset -> ByteString -> ByteString-xtsEncryptGeneric = xtsGeneric ecbEncrypt--xtsDecryptGeneric :: BlockCipher cipher => (cipher,cipher) -> IV cipher -> DataUnitOffset -> ByteString -> ByteString-xtsDecryptGeneric = xtsGeneric ecbDecrypt--xtsGeneric :: BlockCipher cipher-           => (cipher -> B.ByteString -> B.ByteString)-           -> (cipher,cipher)-           -> IV cipher-           -> DataUnitOffset-           -> ByteString-           -> ByteString-xtsGeneric f (cipher, tweakCipher) iv sPoint input = B.concat $ doXts iniTweak $ chunk (blockSize cipher) input-  where encTweak = ecbEncrypt tweakCipher (toBytes iv)-        iniTweak = iterate xtsGFMul encTweak !! fromIntegral sPoint-        doXts _     []     = []-        doXts tweak (i:is) =-            let o = bxor (f cipher $ bxor i tweak) tweak-             in o : doXts (xtsGFMul tweak) is---- | Encrypt using CFB mode in 8 bit output------ Effectively turn a Block cipher in CFB mode into a Stream cipher-cfb8Encrypt :: BlockCipher a => a -> IV a -> B.ByteString -> B.ByteString-cfb8Encrypt ctx origIv msg = B.unsafeCreate (B.length msg) $ \dst -> loop dst origIv msg-  where loop d iv@(IV i) m-            | B.null m  = return ()-            | otherwise = poke d out >> loop (d `plusPtr` 1) ni (B.drop 1 m)-          where m'  = if B.length m < blockSize ctx-                            then m `B.append` B.replicate (blockSize ctx - B.length m) 0-                            else B.take (blockSize ctx) m-                r   = cfbEncrypt ctx iv m'-                out = B.head r-                ni  = IV (B.drop 1 i `B.snoc` out)---- | Decrypt using CFB mode in 8 bit output------ Effectively turn a Block cipher in CFB mode into a Stream cipher-cfb8Decrypt :: BlockCipher a => a -> IV a -> B.ByteString -> B.ByteString-cfb8Decrypt ctx origIv msg = B.unsafeCreate (B.length msg) $ \dst -> loop dst origIv msg-  where loop d iv@(IV i) m-            | B.null m  = return ()-            | otherwise = poke d out >> loop (d `plusPtr` 1) ni (B.drop 1 m)-          where m'  = if B.length m < blockSize ctx-                            then m `B.append` B.replicate (blockSize ctx - B.length m) 0-                            else B.take (blockSize ctx) m-                r   = cfbDecrypt ctx iv m'-                out = B.head r-                ni  = IV (B.drop 1 i `B.snoc` B.head m')--chunk :: Int -> ByteString -> [ByteString]-chunk sz bs = split bs-  where split b | B.length b <= sz = [b]-                | otherwise        =-                        let (b1, b2) = B.splitAt sz b-                         in b1 : split b2--bxor :: ByteString -> ByteString -> ByteString-bxor src dst = B.pack $ B.zipWith xor src dst
+ Crypto/Cipher/Types/AEAD.hs view
@@ -0,0 +1,63 @@+-- |+-- Module      : Crypto.Cipher.Types.AEAD+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : Stable+-- Portability : Excellent+--+-- AEAD cipher basic types+--+module Crypto.Cipher.Types.AEAD where++import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import Data.Byteable+import Crypto.Cipher.Types.Base+import Crypto.Cipher.Types.Block++-- | Append associated data into the AEAD state+aeadAppendHeader :: BlockCipher a => AEAD a -> ByteString -> AEAD a+aeadAppendHeader (AEAD cipher (AEADState state)) bs =+    AEAD cipher $ AEADState (aeadStateAppendHeader cipher state bs)++-- | Encrypt input and append into the AEAD state+aeadEncrypt :: BlockCipher a => AEAD a -> ByteString -> (ByteString, AEAD a)+aeadEncrypt (AEAD cipher (AEADState state)) input = (output, AEAD cipher (AEADState nst))+  where (output, nst) = aeadStateEncrypt cipher state input++-- | Decrypt input and append into the AEAD state+aeadDecrypt :: BlockCipher a => AEAD a -> ByteString -> (ByteString, AEAD a)+aeadDecrypt (AEAD cipher (AEADState state)) input = (output, AEAD cipher (AEADState nst))+  where (output, nst) = aeadStateDecrypt cipher state input++-- | Finalize the AEAD state and create an authentification tag+aeadFinalize :: BlockCipher a => AEAD a -> Int -> AuthTag+aeadFinalize (AEAD cipher (AEADState state)) len =+    aeadStateFinalize cipher state len++-- | Simple AEAD encryption+aeadSimpleEncrypt :: BlockCipher a+                  => AEAD a        -- ^ A new AEAD Context+                  -> B.ByteString  -- ^ Optional Authentified Header+                  -> B.ByteString  -- ^ Optional Plaintext+                  -> Int           -- ^ Tag length+                  -> (AuthTag, B.ByteString) -- ^ Authentification tag and ciphertext+aeadSimpleEncrypt aeadIni header input taglen = (tag, output)+  where aead                = aeadAppendHeader aeadIni header+        (output, aeadFinal) = aeadEncrypt aead input+        tag                 = aeadFinalize aeadFinal taglen++-- | Simple AEAD decryption+aeadSimpleDecrypt :: BlockCipher a+                  => AEAD a        -- ^ A new AEAD Context+                  -> B.ByteString  -- ^ Optional Authentified Header+                  -> B.ByteString  -- ^ Optional Plaintext+                  -> AuthTag       -- ^ Tag length+                  -> Maybe B.ByteString -- ^ Plaintext+aeadSimpleDecrypt aeadIni header input authTag+    | tag == authTag = Just output+    | otherwise      = Nothing+  where aead                = aeadAppendHeader aeadIni header+        (output, aeadFinal) = aeadDecrypt aead input+        tag                 = aeadFinalize aeadFinal (byteableLength authTag)+
+ Crypto/Cipher/Types/Base.hs view
@@ -0,0 +1,83 @@+-- |+-- Module      : Crypto.Cipher.Types.Base+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : Stable+-- Portability : Excellent+--+-- symmetric cipher basic types+--+module Crypto.Cipher.Types.Base+    ( KeyError(..)+    , KeySizeSpecifier(..)+    , Key(..)+    , IV(..)+    , Cipher(..)+    , AuthTag(..)+    , AEADMode(..)+    , DataUnitOffset+    ) where++import Data.Byteable+import Data.SecureMem+import Data.Word+import Data.ByteString (ByteString)++-- | Possible Error that can be reported when initializating a key+data KeyError =+      KeyErrorTooSmall+    | KeyErrorTooBig+    | KeyErrorInvalid String+    deriving (Show,Eq)++-- | Different specifier for key size in bytes+data KeySizeSpecifier =+      KeySizeRange Int Int -- ^ in the range [min,max]+    | KeySizeEnum  [Int]   -- ^ one of the specified values+    | KeySizeFixed Int     -- ^ a specific size+    deriving (Show,Eq)++-- | Offset inside an XTS data unit, measured in block size.+type DataUnitOffset = Word32++-- | a Key parametrized by the cipher+newtype Key c = Key SecureMem deriving (Eq)++instance ToSecureMem (Key c) where+    toSecureMem (Key sm) = sm+instance Byteable (Key c) where+    toBytes (Key sm) = toBytes sm++-- | an IV parametrized by the cipher+newtype IV c = IV ByteString deriving (Eq)++instance Byteable (IV c) where+    toBytes (IV sm) = sm++-- | Authentification Tag for AE cipher mode+newtype AuthTag = AuthTag ByteString+    deriving (Show)++instance Eq AuthTag where+    (AuthTag a) == (AuthTag b) = constEqBytes a b+instance Byteable AuthTag where+    toBytes (AuthTag bs) = bs++-- | AEAD Mode+data AEADMode =+      AEAD_OCB+    | AEAD_CCM+    | AEAD_EAX+    | AEAD_CWC+    | AEAD_GCM+    deriving (Show,Eq)++-- | Symmetric cipher class.+class Cipher cipher where+    -- | Initialize a cipher context from a key+    cipherInit    :: Key cipher -> cipher+    -- | Cipher name+    cipherName    :: cipher -> String+    -- | return the size of the key required for this cipher.+    -- Some cipher accept any size for key+    cipherKeySize :: cipher -> KeySizeSpecifier
+ Crypto/Cipher/Types/Block.hs view
@@ -0,0 +1,253 @@+-- |+-- Module      : Crypto.Cipher.Types.Block+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : Stable+-- Portability : Excellent+--+-- block cipher basic types+--+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE ViewPatterns #-}+module Crypto.Cipher.Types.Block+    (+    -- * BlockCipher+      BlockCipher(..)+    -- * initialization vector (IV)+    , IV+    , makeIV+    , nullIV+    , ivAdd+    -- * XTS+    , XTS+    -- * AEAD+    , AEAD(..)+    , AEADState(..)+    , AEADModeImpl(..)+    -- * CFB 8 bits+    , cfb8Encrypt+    , cfb8Decrypt+    ) where++import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import qualified Data.ByteString.Internal as B (unsafeCreate)+import Data.Byteable+import Data.Word+import Data.Bits (shiftR, Bits)+import Crypto.Cipher.Types.Base+import Crypto.Cipher.Types.GF+import Crypto.Cipher.Types.Utils+import Foreign.Ptr+import Foreign.Storable++type XTS cipher = (cipher, cipher)+               -> IV cipher        -- ^ Usually represent the Data Unit (e.g. disk sector)+               -> DataUnitOffset   -- ^ Offset in the data unit in number of blocks+               -> ByteString       -- ^ Data+               -> ByteString       -- ^ Processed Data++-- | Symmetric block cipher class+class Cipher cipher => BlockCipher cipher where+    -- | Return the size of block required for this block cipher+    blockSize    :: cipher -> Int++    -- | Encrypt blocks+    --+    -- the input string need to be multiple of the block size+    ecbEncrypt :: cipher -> ByteString -> ByteString++    -- | Decrypt blocks+    --+    -- the input string need to be multiple of the block size+    ecbDecrypt :: cipher -> ByteString -> ByteString++    -- | encrypt using the CBC mode.+    --+    -- input need to be a multiple of the blocksize+    cbcEncrypt :: cipher -> IV cipher -> ByteString -> ByteString+    cbcEncrypt = cbcEncryptGeneric+    -- | decrypt using the CBC mode.+    --+    -- input need to be a multiple of the blocksize+    cbcDecrypt :: cipher -> IV cipher -> ByteString -> ByteString+    cbcDecrypt = cbcDecryptGeneric++    -- | encrypt using the CFB mode.+    --+    -- input need to be a multiple of the blocksize+    cfbEncrypt :: cipher -> IV cipher -> ByteString -> ByteString+    cfbEncrypt = cfbEncryptGeneric+    -- | decrypt using the CFB mode.+    --+    -- input need to be a multiple of the blocksize+    cfbDecrypt :: cipher -> IV cipher -> ByteString -> ByteString+    cfbDecrypt = cfbDecryptGeneric++    -- | combine using the CTR mode.+    --+    -- CTR mode produce a stream of randomized data that is combined+    -- (by XOR operation) with the input stream.+    --+    -- encryption and decryption are the same operation.+    --+    -- input can be of any size+    ctrCombine :: cipher -> IV cipher -> ByteString -> ByteString+    ctrCombine = ctrCombineGeneric++    -- | encrypt using the XTS mode.+    --+    -- input need to be a multiple of the blocksize, and the cipher+    -- need to process 128 bits block only+    xtsEncrypt :: (cipher, cipher)+               -> IV cipher        -- ^ Usually represent the Data Unit (e.g. disk sector)+               -> DataUnitOffset   -- ^ Offset in the data unit in number of blocks+               -> ByteString       -- ^ Plaintext+               -> ByteString       -- ^ Ciphertext+    xtsEncrypt = xtsEncryptGeneric++    -- | decrypt using the XTS mode.+    --+    -- input need to be a multiple of the blocksize, and the cipher+    -- need to process 128 bits block only+    xtsDecrypt :: (cipher, cipher)+               -> IV cipher        -- ^ Usually represent the Data Unit (e.g. disk sector)+               -> DataUnitOffset   -- ^ Offset in the data unit in number of blocks+               -> ByteString       -- ^ Ciphertext+               -> ByteString       -- ^ Plaintext+    xtsDecrypt = xtsDecryptGeneric++    -- | Initialize a new AEAD State+    --+    -- When Nothing is returns, it means the mode is not handled.+    aeadInit :: Byteable iv => AEADMode -> cipher -> iv -> Maybe (AEAD cipher)+    aeadInit _ _ _ = Nothing++-- | Authenticated Encryption with Associated Data algorithms+data AEAD cipher = AEAD cipher (AEADState cipher)++-- | Wrapper for any AEADState+data AEADState cipher = forall st . AEADModeImpl cipher st => AEADState st++-- | Class of AEAD Mode implementation+class BlockCipher cipher => AEADModeImpl cipher state where+    aeadStateAppendHeader :: cipher -> state -> ByteString -> state+    aeadStateEncrypt      :: cipher -> state -> ByteString -> (ByteString, state)+    aeadStateDecrypt      :: cipher -> state -> ByteString -> (ByteString, state)+    aeadStateFinalize     :: cipher -> state -> Int -> AuthTag++-- | Create an IV for a specified block cipher+makeIV :: (Byteable b, BlockCipher c) => b -> Maybe (IV c)+makeIV b = toIV undefined+  where toIV :: BlockCipher c => c -> Maybe (IV c)+        toIV cipher+          | byteableLength b == sz = Just (IV $ toBytes b)+          | otherwise              = Nothing+          where sz = blockSize cipher++-- | Create an IV that is effectively representing the number 0+nullIV :: BlockCipher c => IV c+nullIV = toIV undefined+  where toIV :: BlockCipher c => c -> IV c+        toIV cipher = IV $ B.replicate (blockSize cipher) 0++-- | Increment an IV by a number.+--+-- Assume the IV is in Big Endian format.+ivAdd :: BlockCipher c => IV c -> Int -> IV c+ivAdd (IV b) i = IV $ snd $ B.mapAccumR addCarry i b+  where addCarry :: Int -> Word8 -> (Int, Word8)+        addCarry acc w+            | acc == 0  = (0, w)+            | otherwise = let (hi,lo) = acc `divMod` 256+                              nw      = lo + (fromIntegral w)+                           in (hi + (nw `shiftR` 8), fromIntegral nw)++cbcEncryptGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString+cbcEncryptGeneric cipher (IV ivini) input = B.concat $ doEnc ivini $ chunk (blockSize cipher) input+  where doEnc _  []     = []+        doEnc iv (i:is) =+            let o = ecbEncrypt cipher $ bxor iv i+             in o : doEnc o is++cbcDecryptGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString+cbcDecryptGeneric cipher (IV ivini) input = B.concat $ doDec ivini $ chunk (blockSize cipher) input+  where doDec _  []     = []+        doDec iv (i:is) =+            let o = bxor iv $ ecbDecrypt cipher i+             in o : doDec i is++cfbEncryptGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString+cfbEncryptGeneric cipher (IV ivini) input = B.concat $ doEnc ivini $ chunk (blockSize cipher) input+  where doEnc _  []     = []+        doEnc iv (i:is) =+            let o = bxor i $ ecbEncrypt cipher iv+             in o : doEnc o is++cfbDecryptGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString+cfbDecryptGeneric cipher (IV ivini) input = B.concat $ doDec ivini $ chunk (blockSize cipher) input+  where doDec _  []     = []+        doDec iv (i:is) =+            let o = bxor i $ ecbEncrypt cipher iv+             in o : doDec i is++ctrCombineGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString+ctrCombineGeneric cipher ivini input = B.concat $ doCnt ivini $ chunk (blockSize cipher) input+  where doCnt _  [] = []+        doCnt iv (i:is) =+            let ivEnc = ecbEncrypt cipher (toBytes iv)+             in bxor i ivEnc : doCnt (ivAdd iv 1) is++xtsEncryptGeneric :: BlockCipher cipher => XTS cipher+xtsEncryptGeneric = xtsGeneric ecbEncrypt++xtsDecryptGeneric :: BlockCipher cipher => XTS cipher+xtsDecryptGeneric = xtsGeneric ecbDecrypt++xtsGeneric :: BlockCipher cipher+           => (cipher -> B.ByteString -> B.ByteString)+           -> (cipher, cipher)+           -> IV cipher+           -> DataUnitOffset+           -> ByteString+           -> ByteString+xtsGeneric f (cipher, tweakCipher) iv sPoint input+    | blockSize cipher /= 16 = error "XTS mode is only available with cipher that have a block size of 128 bits"+    | otherwise = B.concat $ doXts iniTweak $ chunk (blockSize cipher) input+  where encTweak = ecbEncrypt tweakCipher (toBytes iv)+        iniTweak = iterate xtsGFMul encTweak !! fromIntegral sPoint+        doXts _     []     = []+        doXts tweak (i:is) =+            let o = bxor (f cipher $ bxor i tweak) tweak+             in o : doXts (xtsGFMul tweak) is++-- | Encrypt using CFB mode in 8 bit output+--+-- Effectively turn a Block cipher in CFB mode into a Stream cipher+cfb8Encrypt :: BlockCipher a => a -> IV a -> B.ByteString -> B.ByteString+cfb8Encrypt ctx origIv msg = B.unsafeCreate (B.length msg) $ \dst -> loop dst origIv msg+  where loop d iv@(IV i) m+            | B.null m  = return ()+            | otherwise = poke d out >> loop (d `plusPtr` 1) ni (B.drop 1 m)+          where m'  = if B.length m < blockSize ctx+                            then m `B.append` B.replicate (blockSize ctx - B.length m) 0+                            else B.take (blockSize ctx) m+                r   = cfbEncrypt ctx iv m'+                out = B.head r+                ni  = IV (B.drop 1 i `B.snoc` out)++-- | Decrypt using CFB mode in 8 bit output+--+-- Effectively turn a Block cipher in CFB mode into a Stream cipher+cfb8Decrypt :: BlockCipher a => a -> IV a -> B.ByteString -> B.ByteString+cfb8Decrypt ctx origIv msg = B.unsafeCreate (B.length msg) $ \dst -> loop dst origIv msg+  where loop d iv@(IV i) m+            | B.null m  = return ()+            | otherwise = poke d out >> loop (d `plusPtr` 1) ni (B.drop 1 m)+          where m'  = if B.length m < blockSize ctx+                            then m `B.append` B.replicate (blockSize ctx - B.length m) 0+                            else B.take (blockSize ctx) m+                r   = cfbDecrypt ctx iv m'+                out = B.head r+                ni  = IV (B.drop 1 i `B.snoc` B.head m')
+ Crypto/Cipher/Types/BlockIO.hs view
@@ -0,0 +1,186 @@+-- |+-- Module      : Crypto.Cipher.Types.Block+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : Stable+-- Portability : Excellent+--+-- block cipher basic types+--+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE ViewPatterns #-}+module Crypto.Cipher.Types.BlockIO+    ( BlockCipherIO(..)+    , PtrDest+    , PtrSource+    , PtrIV+    , BufferLength+    , onBlock+    ) where++import Control.Applicative+import Data.Word+import Data.ByteString (ByteString)+import qualified Data.ByteString.Internal as B (fromForeignPtr, memcpy)+import Data.Byteable+import Data.Bits (xor, Bits)+import Foreign.Storable (poke, peek, Storable)+--import Foreign.Ptr (plusPtr, Ptr, castPtr, nullPtr)+import Crypto.Cipher.Types.Block+import Foreign.Ptr+import Foreign.ForeignPtr (newForeignPtr_)++-- | pointer to the destination data+type PtrDest   = Ptr Word8++-- | pointer to the source data+type PtrSource = Ptr Word8++-- | pointer to the IV data+type PtrIV     = Ptr Word8++-- | Length of the pointed data+type BufferLength = Word32++-- | Symmetric block cipher class, mutable API+class BlockCipher cipher => BlockCipherIO cipher where+    -- | Encrypt using the ECB mode.+    --+    -- input need to be a multiple of the blocksize+    ecbEncryptMutable :: cipher -> PtrDest -> PtrSource -> BufferLength -> IO ()++    -- | Decrypt using the ECB mode.+    --+    -- input need to be a multiple of the blocksize+    ecbDecryptMutable :: cipher -> PtrDest -> PtrSource -> BufferLength -> IO ()++    -- | encrypt using the CBC mode.+    --+    -- input need to be a multiple of the blocksize+    cbcEncryptMutable :: cipher -> PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ()+    cbcEncryptMutable = cbcEncryptGeneric++    -- | decrypt using the CBC mode.+    --+    -- input need to be a multiple of the blocksize+    cbcDecryptMutable :: cipher -> PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ()+    cbcDecryptMutable = cbcDecryptGeneric++{-+    -- | encrypt using the CFB mode.+    --+    -- input need to be a multiple of the blocksize+    cfbEncryptMutable :: cipher -> PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ()+    cfbEncryptMutable = cfbEncryptGeneric++    -- | decrypt using the CFB mode.+    --+    -- input need to be a multiple of the blocksize+    cfbDecryptMutable :: cipher -> PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ()+    cfbDecryptMutable = cfbDecryptGeneric++    -- | combine using the CTR mode.+    --+    -- CTR mode produce a stream of randomized data that is combined+    -- (by XOR operation) with the input stream.+    --+    -- encryption and decryption are the same operation.+    --+    -- input can be of any size+    ctrCombineMutable :: cipher -> PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ()+    ctrCombineMutable = ctrCombineGeneric++    -- | encrypt using the XTS mode.+    --+    -- input need to be a multiple of the blocksize+    xtsEncryptMutable :: (cipher, cipher) -> PtrIV -> DataUnitOffset -> PtrDest -> PtrSource -> BufferLength -> IO ()+    xtsEncryptMutable = xtsEncryptGeneric+    -- | decrypt using the XTS mode.+    --+    -- input need to be a multiple of the blocksize+    xtsDecryptMutable :: (cipher, cipher) -> PtrIV -> DataUnitOffset -> PtrDest -> PtrSource -> BufferLength -> IO ()+    xtsDecryptMutable = xtsDecryptGeneric+-}++cbcEncryptGeneric :: BlockCipherIO cipher => cipher -> PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ()+cbcEncryptGeneric cipher = loopBS cipher encrypt+  where encrypt bs iv d s = do+            mutableXor d iv s bs+            ecbEncryptMutable cipher d d (fromIntegral bs)+            return s++cbcDecryptGeneric :: BlockCipherIO cipher => cipher -> PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ()+cbcDecryptGeneric cipher = loopBS cipher decrypt+  where decrypt bs iv d s = do+            ecbEncryptMutable cipher d s (fromIntegral bs)+            -- FIXME only work if s != d+            mutableXor d iv d bs+            return d++{-+cfbEncryptGeneric :: BlockCipherIO cipher => cipher -> PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ()+cfbEncryptGeneric cipher = loopBS cipher encrypt+  where encrypt bs iv d s = do+            ecbEncryptMutable cipher d iv (fromIntegral bs)+            mutableXor d d s bs+            return d+++cfbDecryptGeneric :: BlockCipherIO cipher => cipher -> PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ()+cfbDecryptGeneric cipher = loopBS cipher decrypt+  where decrypt bs iv d s = do+            ecbEncryptMutable cipher d iv (fromIntegral bs)+            mutableXor d d s bs+            return s++ctrCombineGeneric :: BlockCipherIO cipher => cipher -> PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ()+ctrCombineGeneric cipher ivini dst src len = return () {-B.concat $ doCnt ivini $ chunk (blockSize cipher) input+  where doCnt _  [] = []+        doCnt iv (i:is) =+            let ivEnc = ecbEncrypt cipher (toBytes iv)+             in bxor i ivEnc : doCnt (ivAdd iv 1) is-}+-}++-- | Helper to use a purer interface+onBlock :: BlockCipherIO cipher+        => cipher+        -> (ByteString -> ByteString)+        -> PtrDest+        -> PtrSource+        -> BufferLength+        -> IO ()+onBlock cipher f dst src len = loopBS cipher wrap nullPtr dst src len+  where wrap bs fakeIv d s = do+            fSrc <- newForeignPtr_ s+            let res = f (B.fromForeignPtr fSrc 0 bs)+            withBytePtr res $ \r -> B.memcpy d r bs+            return fakeIv++loopBS :: BlockCipherIO cipher+       => cipher+       -> (Int -> PtrIV -> PtrDest -> PtrSource -> IO PtrIV)+       -> PtrIV -> PtrDest -> PtrSource -> BufferLength+       -> IO ()+loopBS cipher f iv dst src len = loop iv dst src len+  where bs = blockSize cipher+        loop _ _ _ 0 = return ()+        loop i d s n = do+            newIV <- f bs i d s+            loop newIV (d `plusPtr` bs) (s `plusPtr` bs) (n - fromIntegral bs)++mutableXor :: PtrDest -> PtrSource -> PtrIV -> Int -> IO ()+mutableXor (to64 -> dst) (to64 -> src) (to64 -> iv) 16 = do+    peeksAndPoke dst src iv+    peeksAndPoke (dst `plusPtr` 8) (src `plusPtr` 8) ((iv `plusPtr` 8) :: Ptr Word64)+mutableXor (to64 -> dst) (to64 -> src) (to64 -> iv) 8 = do+    peeksAndPoke dst src iv+mutableXor dst src iv len = loop dst src iv len+  where loop _ _ _ 0 = return ()+        loop d s i n = peeksAndPoke d s i >> loop (d `plusPtr` 1) (s `plusPtr` 1) (i `plusPtr` 1) (n-1)++to64 :: Ptr Word8 -> Ptr Word64+to64 = castPtr++peeksAndPoke :: (Bits a, Storable a) => Ptr a -> Ptr a -> Ptr a -> IO ()+peeksAndPoke dst a b = (xor <$> peek a <*> peek b) >>= poke dst
+ Crypto/Cipher/Types/OfIO.hs view
@@ -0,0 +1,183 @@+-- |+-- Module      : Crypto.Cipher.Types.Modes+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : Stable+-- Portability : Excellent+--+-- block cipher modes immutable interfaces+--+module Crypto.Cipher.Types.OfIO+    (+    -- * ECB+      ecbEncryptOfIO+    , ecbDecryptOfIO+{-+    -- * CBC+    , cbcEncryptOfIO+    , cbcDecryptOfIO+    -- * CFB+    , cfbEncryptOfIO+    , cfbDecryptOfIO+    , cfb8EncryptOfIO+    , cfb8DecryptOfIO+    -- * CTR+    , ctrCombineOfIO+    -- * XTS+    , xtsEncryptOfIO+    , xtsDecryptOfIO+-}+    ) where++import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import qualified Data.ByteString.Internal as B+import Data.Byteable+--import Crypto.Cipher.Types.Base+import Crypto.Cipher.Types.Block+import Crypto.Cipher.Types.BlockIO+--import Foreign.Storable (poke)+--import Foreign.Ptr++isBlockSized :: (BlockCipher cipher, BlockCipherIO cipher) => cipher -> Int -> Bool+isBlockSized cipher bsLen = (bsLen `mod` blockSize cipher) == 0++notBlockSized :: (BlockCipher cipher, BlockCipherIO cipher) => cipher -> a+notBlockSized = undefined++withDest :: BlockCipherIO cipher+         => cipher+         -> ByteString+         -> (PtrDest -> PtrSource -> BufferLength -> IO ())+         -> ByteString+withDest cipher bs f+    | B.null bs                     = B.empty+    | not (isBlockSized cipher len) = notBlockSized cipher+    | otherwise                     =+        B.unsafeCreate len $ \dst ->+        withBytePtr bs     $ \src ->+        f dst src (fromIntegral len)+  where len = B.length bs++{-+withDestIV :: BlockCipherIO cipher+           => cipher+           -> IV cipher+           -> ByteString+           -> (PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ())+           -> ByteString+withDestIV cipher (IV iv) bs f+    | B.null bs                     = B.empty+    | not (isBlockSized cipher len) = notBlockSized cipher+    | otherwise                     =+        B.unsafeCreate len $ \dst   ->+        withBytePtr iv     $ \ivPtr ->+        withBytePtr bs     $ \src   ->+        f ivPtr dst src (fromIntegral len)+  where len = B.length bs++withDestIVAnySize :: BlockCipherIO cipher+                  => IV cipher+                  -> ByteString+                  -> (PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ())+                  -> ByteString+withDestIVAnySize (IV iv) bs f+    | B.null bs = B.empty+    | otherwise =+        B.unsafeCreate len $ \dst   ->+        withBytePtr iv     $ \ivPtr ->+        withBytePtr bs     $ \src   ->+        f ivPtr dst src (fromIntegral len)+  where len = B.length bs+-}++-- | Encrypt using the ECB mode.+--+-- input need to be a multiple of the blocksize+ecbEncryptOfIO :: BlockCipherIO cipher => cipher -> ByteString -> ByteString+ecbEncryptOfIO cipher bs = withDest cipher bs $ ecbEncryptMutable cipher++-- | Decrypt using the ECB mode.+--+-- input need to be a multiple of the blocksize+ecbDecryptOfIO :: BlockCipherIO cipher => cipher -> ByteString -> ByteString+ecbDecryptOfIO cipher bs = withDest cipher bs $ ecbEncryptMutable cipher++{-+-- | encrypt using the CBC mode.+--+-- input need to be a multiple of the blocksize+cbcEncryptOfIO :: BlockCipherIO cipher => cipher -> IV cipher -> ByteString -> ByteString+cbcEncryptOfIO cipher iv bs = withDestIV cipher iv bs $ cbcEncryptMutable cipher++-- | decrypt using the CBC mode.+--+-- input need to be a multiple of the blocksize+cbcDecryptOfIO :: BlockCipherIO cipher => cipher -> IV cipher -> ByteString -> ByteString+cbcDecryptOfIO cipher iv bs = withDestIV cipher iv bs $ cbcDecryptMutable cipher++-- | encrypt using the CFB mode.+--+-- input need to be a multiple of the blocksize+cfbEncryptOfIO :: BlockCipherIO cipher => cipher -> IV cipher -> ByteString -> ByteString+cfbEncryptOfIO cipher iv bs = withDestIV cipher iv bs $ cfbEncryptMutable cipher++-- | decrypt using the CFB mode.+--+-- input need to be a multiple of the blocksize+cfbDecryptOfIO :: BlockCipherIO cipher => cipher -> IV cipher -> ByteString -> ByteString+cfbDecryptOfIO cipher iv bs = withDestIV cipher iv bs $ cfbDecryptMutable cipher++-- | combine using the CTR mode.+--+-- CTR mode produce a stream of randomized data that is combined+-- (by XOR operation) with the input stream.+--+-- encryption and decryption are the same operation.+--+-- input can be of any size+ctrCombineOfIO :: BlockCipherIO cipher => cipher -> IV cipher -> ByteString -> ByteString+ctrCombineOfIO cipher iv bs = withDestIVAnySize iv bs $ cfbDecryptMutable cipher+ +-- | encrypt using the XTS mode.+--+-- input need to be a multiple of the blocksize+xtsEncryptOfIO :: BlockCipherIO cipher => (cipher, cipher) -> IV cipher -> DataUnitOffset -> ByteString -> ByteString+xtsEncryptOfIO ciphers@(c1,_) iv ofs bs = withDestIV c1 iv bs $ \ivPtr -> xtsEncryptMutable ciphers ivPtr ofs++-- | decrypt using the XTS mode.+--+-- input need to be a multiple of the blocksize+xtsDecryptOfIO :: BlockCipherIO cipher => (cipher, cipher) -> IV cipher -> DataUnitOffset -> ByteString -> ByteString+xtsDecryptOfIO ciphers@(c1,_) iv ofs bs = withDestIV c1 iv bs $ \ivPtr -> xtsDecryptMutable ciphers ivPtr ofs++-- | Encrypt using CFB mode in 8 bit output+--+-- Effectively turn a Block cipher in CFB mode into a Stream cipher+cfb8EncryptOfIO :: BlockCipherIO a => a -> IV a -> B.ByteString -> B.ByteString+cfb8EncryptOfIO ctx origIv msg = B.unsafeCreate (B.length msg) $ \dst -> loop dst origIv msg+  where loop d iv@(IV i) m+            | B.null m  = return ()+            | otherwise = poke d out >> loop (d `plusPtr` 1) ni (B.drop 1 m)+          where m'  = if B.length m < blockSize ctx+                            then m `B.append` B.replicate (blockSize ctx - B.length m) 0+                            else B.take (blockSize ctx) m+                r   = cfbEncryptOfIO ctx iv m'+                out = B.head r+                ni  = IV (B.drop 1 i `B.snoc` out)++-- | Decrypt using CFB mode in 8 bit output+--+-- Effectively turn a Block cipher in CFB mode into a Stream cipher+cfb8DecryptOfIO :: BlockCipherIO a => a -> IV a -> B.ByteString -> B.ByteString+cfb8DecryptOfIO ctx origIv msg = B.unsafeCreate (B.length msg) $ \dst -> loop dst origIv msg+  where loop d iv@(IV i) m+            | B.null m  = return ()+            | otherwise = poke d out >> loop (d `plusPtr` 1) ni (B.drop 1 m)+          where m'  = if B.length m < blockSize ctx+                            then m `B.append` B.replicate (blockSize ctx - B.length m) 0+                            else B.take (blockSize ctx) m+                r   = cfbDecryptOfIO ctx iv m'+                out = B.head r+                ni  = IV (B.drop 1 i `B.snoc` B.head m')+-}
+ Crypto/Cipher/Types/Stream.hs view
@@ -0,0 +1,20 @@+-- |+-- Module      : Crypto.Cipher.Types.Stream+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : Stable+-- Portability : Excellent+--+-- stream cipher basic types+--+module Crypto.Cipher.Types.Stream+    ( StreamCipher(..)+    ) where++import Crypto.Cipher.Types.Base+import Data.ByteString (ByteString)++-- | Symmetric stream cipher class+class Cipher cipher => StreamCipher cipher where+    -- | Combine using the stream cipher+    streamCombine :: cipher -> ByteString -> (ByteString, cipher)
+ Crypto/Cipher/Types/Unsafe.hs view
@@ -0,0 +1,20 @@+-- |+-- Module      : Crypto.Cipher.Types.Unsafe+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : Stable+-- Portability : Excellent+--+-- mutable and unsafe interface for Block ciphers.+-- export a BlockCipherIO class+--+module Crypto.Cipher.Types.Unsafe+    ( BlockCipherIO(..)+    , BufferLength+    , PtrDest+    , PtrSource+    , PtrIV+    , onBlock+    ) where++import Crypto.Cipher.Types.BlockIO
+ Crypto/Cipher/Types/Utils.hs view
@@ -0,0 +1,24 @@+-- |+-- Module      : Crypto.Cipher.Types.Utils+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : Stable+-- Portability : Excellent+--+-- basic utility for cipher related stuff+--+module Crypto.Cipher.Types.Utils where++import Data.Bits (xor)+import Data.ByteString (ByteString)+import qualified Data.ByteString as B++chunk :: Int -> ByteString -> [ByteString]+chunk sz bs = split bs+  where split b | B.length b <= sz = [b]+                | otherwise        =+                        let (b1, b2) = B.splitAt sz b+                         in b1 : split b2++bxor :: ByteString -> ByteString -> ByteString+bxor src dst = B.pack $ B.zipWith xor src dst
crypto-cipher-types.cabal view
@@ -1,5 +1,5 @@ Name:                crypto-cipher-types-Version:             0.0.7+Version:             0.0.8 Synopsis:            Generic cryptography cipher types Description:         Generic cryptography cipher types License:             BSD3@@ -16,7 +16,15 @@  Library   Exposed-modules:   Crypto.Cipher.Types+                   , Crypto.Cipher.Types.Unsafe   Other-modules:     Crypto.Cipher.Types.GF+                   , Crypto.Cipher.Types.Block+                   , Crypto.Cipher.Types.BlockIO+                   , Crypto.Cipher.Types.Stream+                   , Crypto.Cipher.Types.OfIO+                   , Crypto.Cipher.Types.AEAD+                   , Crypto.Cipher.Types.Base+                   , Crypto.Cipher.Types.Utils   Build-depends:     base >= 4 && < 5                    , bytestring                    , byteable >= 0.1.1