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 +6/−328
- Crypto/Cipher/Types/AEAD.hs +63/−0
- Crypto/Cipher/Types/Base.hs +83/−0
- Crypto/Cipher/Types/Block.hs +253/−0
- Crypto/Cipher/Types/BlockIO.hs +186/−0
- Crypto/Cipher/Types/OfIO.hs +183/−0
- Crypto/Cipher/Types/Stream.hs +20/−0
- Crypto/Cipher/Types/Unsafe.hs +20/−0
- Crypto/Cipher/Types/Utils.hs +24/−0
- crypto-cipher-types.cabal +9/−1
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