wip in cipher refactoring
This commit is contained in:
parent
3b19f768ce
commit
6216137f43
@ -16,18 +16,14 @@ module Crypto.Cipher.Types
|
|||||||
, StreamCipher(..)
|
, StreamCipher(..)
|
||||||
, DataUnitOffset
|
, DataUnitOffset
|
||||||
, KeySizeSpecifier(..)
|
, KeySizeSpecifier(..)
|
||||||
, KeyError(..)
|
|
||||||
, AEAD(..)
|
, AEAD(..)
|
||||||
, AEADState(..)
|
, AEADState(..)
|
||||||
, AEADMode(..)
|
, AEADMode(..)
|
||||||
, AEADModeImpl(..)
|
, AEADModeImpl(..)
|
||||||
, cfb8Encrypt
|
-- , cfb8Encrypt
|
||||||
, cfb8Decrypt
|
-- , cfb8Decrypt
|
||||||
-- * AEAD functions
|
-- * AEAD functions
|
||||||
, module Crypto.Cipher.Types.AEAD
|
, module Crypto.Cipher.Types.AEAD
|
||||||
-- * Key type and constructor
|
|
||||||
, Key
|
|
||||||
, makeKey
|
|
||||||
-- * Initial Vector type and constructor
|
-- * Initial Vector type and constructor
|
||||||
, IV
|
, IV
|
||||||
, makeIV
|
, makeIV
|
||||||
@ -37,24 +33,7 @@ module Crypto.Cipher.Types
|
|||||||
, AuthTag(..)
|
, AuthTag(..)
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Data.SecureMem
|
|
||||||
import Data.Byteable
|
|
||||||
import Crypto.Cipher.Types.Base
|
import Crypto.Cipher.Types.Base
|
||||||
import Crypto.Cipher.Types.Block
|
import Crypto.Cipher.Types.Block
|
||||||
import Crypto.Cipher.Types.Stream
|
import Crypto.Cipher.Types.Stream
|
||||||
import Crypto.Cipher.Types.AEAD
|
import Crypto.Cipher.Types.AEAD
|
||||||
|
|
||||||
-- | Create a Key for a specified cipher
|
|
||||||
makeKey :: (ToSecureMem b, Cipher c) => b -> Either KeyError (Key c)
|
|
||||||
makeKey b = toKey undefined
|
|
||||||
where sm = toSecureMem b
|
|
||||||
smLen = byteableLength sm
|
|
||||||
toKey :: Cipher c => c -> Either KeyError (Key c)
|
|
||||||
toKey cipher = case cipherKeySize cipher of
|
|
||||||
KeySizeRange mi ma | smLen < mi -> Left KeyErrorTooSmall
|
|
||||||
| smLen > ma -> Left KeyErrorTooBig
|
|
||||||
| otherwise -> Right $ Key sm
|
|
||||||
KeySizeEnum l | smLen `elem` l -> Right $ Key sm
|
|
||||||
| otherwise -> Left $ KeyErrorInvalid ("valid size: " ++ show l)
|
|
||||||
KeySizeFixed v | smLen == v -> Right $ Key sm
|
|
||||||
| otherwise -> Left $ KeyErrorInvalid ("valid size: " ++ show v)
|
|
||||||
|
|||||||
@ -7,10 +7,9 @@
|
|||||||
--
|
--
|
||||||
-- symmetric cipher basic types
|
-- symmetric cipher basic types
|
||||||
--
|
--
|
||||||
|
{-# LANGUAGE ExistentialQuantification #-}
|
||||||
module Crypto.Cipher.Types.Base
|
module Crypto.Cipher.Types.Base
|
||||||
( KeyError(..)
|
( KeySizeSpecifier(..)
|
||||||
, KeySizeSpecifier(..)
|
|
||||||
, Key(..)
|
|
||||||
, IV(..)
|
, IV(..)
|
||||||
, Cipher(..)
|
, Cipher(..)
|
||||||
, AuthTag(..)
|
, AuthTag(..)
|
||||||
@ -23,12 +22,8 @@ import Data.SecureMem
|
|||||||
import Data.Word
|
import Data.Word
|
||||||
import Data.ByteString (ByteString)
|
import Data.ByteString (ByteString)
|
||||||
|
|
||||||
-- | Possible Error that can be reported when initializating a key
|
import Crypto.Internal.ByteArray
|
||||||
data KeyError =
|
import Crypto.Error
|
||||||
KeyErrorTooSmall
|
|
||||||
| KeyErrorTooBig
|
|
||||||
| KeyErrorInvalid String
|
|
||||||
deriving (Show,Eq)
|
|
||||||
|
|
||||||
-- | Different specifier for key size in bytes
|
-- | Different specifier for key size in bytes
|
||||||
data KeySizeSpecifier =
|
data KeySizeSpecifier =
|
||||||
@ -40,19 +35,10 @@ data KeySizeSpecifier =
|
|||||||
-- | Offset inside an XTS data unit, measured in block size.
|
-- | Offset inside an XTS data unit, measured in block size.
|
||||||
type DataUnitOffset = Word32
|
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
|
-- | an IV parametrized by the cipher
|
||||||
newtype IV c = IV ByteString deriving (Eq)
|
data IV c = forall byteArray . ByteArray byteArray => IV byteArray
|
||||||
|
|
||||||
instance Byteable (IV c) where
|
instance ByteArray (IV c) where
|
||||||
toBytes (IV sm) = sm
|
|
||||||
|
|
||||||
-- | Authentification Tag for AE cipher mode
|
-- | Authentification Tag for AE cipher mode
|
||||||
newtype AuthTag = AuthTag ByteString
|
newtype AuthTag = AuthTag ByteString
|
||||||
@ -75,7 +61,7 @@ data AEADMode =
|
|||||||
-- | Symmetric cipher class.
|
-- | Symmetric cipher class.
|
||||||
class Cipher cipher where
|
class Cipher cipher where
|
||||||
-- | Initialize a cipher context from a key
|
-- | Initialize a cipher context from a key
|
||||||
cipherInit :: Key cipher -> cipher
|
cipherInit :: ByteArray key => key -> CryptoFailable cipher
|
||||||
-- | Cipher name
|
-- | Cipher name
|
||||||
cipherName :: cipher -> String
|
cipherName :: cipher -> String
|
||||||
-- | return the size of the key required for this cipher.
|
-- | return the size of the key required for this cipher.
|
||||||
|
|||||||
@ -26,8 +26,8 @@ module Crypto.Cipher.Types.Block
|
|||||||
, AEADState(..)
|
, AEADState(..)
|
||||||
, AEADModeImpl(..)
|
, AEADModeImpl(..)
|
||||||
-- * CFB 8 bits
|
-- * CFB 8 bits
|
||||||
, cfb8Encrypt
|
--, cfb8Encrypt
|
||||||
, cfb8Decrypt
|
--, cfb8Decrypt
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Data.ByteString (ByteString)
|
import Data.ByteString (ByteString)
|
||||||
@ -39,6 +39,9 @@ import Data.Bits (shiftR)
|
|||||||
import Crypto.Cipher.Types.Base
|
import Crypto.Cipher.Types.Base
|
||||||
import Crypto.Cipher.Types.GF
|
import Crypto.Cipher.Types.GF
|
||||||
import Crypto.Cipher.Types.Utils
|
import Crypto.Cipher.Types.Utils
|
||||||
|
|
||||||
|
import Crypto.Internal.ByteArray
|
||||||
|
|
||||||
import Foreign.Ptr
|
import Foreign.Ptr
|
||||||
import Foreign.Storable
|
import Foreign.Storable
|
||||||
|
|
||||||
@ -56,33 +59,33 @@ class Cipher cipher => BlockCipher cipher where
|
|||||||
-- | Encrypt blocks
|
-- | Encrypt blocks
|
||||||
--
|
--
|
||||||
-- the input string need to be multiple of the block size
|
-- the input string need to be multiple of the block size
|
||||||
ecbEncrypt :: cipher -> ByteString -> ByteString
|
ecbEncrypt :: ByteArray ba => cipher -> ba -> ba
|
||||||
|
|
||||||
-- | Decrypt blocks
|
-- | Decrypt blocks
|
||||||
--
|
--
|
||||||
-- the input string need to be multiple of the block size
|
-- the input string need to be multiple of the block size
|
||||||
ecbDecrypt :: cipher -> ByteString -> ByteString
|
ecbDecrypt :: ByteArray ba => cipher -> ba -> ba
|
||||||
|
|
||||||
-- | encrypt using the CBC mode.
|
-- | encrypt using the CBC mode.
|
||||||
--
|
--
|
||||||
-- input need to be a multiple of the blocksize
|
-- input need to be a multiple of the blocksize
|
||||||
cbcEncrypt :: cipher -> IV cipher -> ByteString -> ByteString
|
cbcEncrypt :: ByteArray ba => cipher -> IV cipher -> ba -> ba
|
||||||
cbcEncrypt = cbcEncryptGeneric
|
cbcEncrypt = cbcEncryptGeneric
|
||||||
-- | decrypt using the CBC mode.
|
-- | decrypt using the CBC mode.
|
||||||
--
|
--
|
||||||
-- input need to be a multiple of the blocksize
|
-- input need to be a multiple of the blocksize
|
||||||
cbcDecrypt :: cipher -> IV cipher -> ByteString -> ByteString
|
cbcDecrypt :: ByteArray ba => cipher -> IV cipher -> ba -> ba
|
||||||
cbcDecrypt = cbcDecryptGeneric
|
cbcDecrypt = cbcDecryptGeneric
|
||||||
|
|
||||||
-- | encrypt using the CFB mode.
|
-- | encrypt using the CFB mode.
|
||||||
--
|
--
|
||||||
-- input need to be a multiple of the blocksize
|
-- input need to be a multiple of the blocksize
|
||||||
cfbEncrypt :: cipher -> IV cipher -> ByteString -> ByteString
|
cfbEncrypt :: ByteArray ba => cipher -> IV cipher -> ba -> ba
|
||||||
cfbEncrypt = cfbEncryptGeneric
|
cfbEncrypt = cfbEncryptGeneric
|
||||||
-- | decrypt using the CFB mode.
|
-- | decrypt using the CFB mode.
|
||||||
--
|
--
|
||||||
-- input need to be a multiple of the blocksize
|
-- input need to be a multiple of the blocksize
|
||||||
cfbDecrypt :: cipher -> IV cipher -> ByteString -> ByteString
|
cfbDecrypt :: ByteArray ba => cipher -> IV cipher -> ba -> ba
|
||||||
cfbDecrypt = cfbDecryptGeneric
|
cfbDecrypt = cfbDecryptGeneric
|
||||||
|
|
||||||
-- | combine using the CTR mode.
|
-- | combine using the CTR mode.
|
||||||
@ -93,9 +96,17 @@ class Cipher cipher => BlockCipher cipher where
|
|||||||
-- encryption and decryption are the same operation.
|
-- encryption and decryption are the same operation.
|
||||||
--
|
--
|
||||||
-- input can be of any size
|
-- input can be of any size
|
||||||
ctrCombine :: cipher -> IV cipher -> ByteString -> ByteString
|
ctrCombine :: ByteArray ba => cipher -> IV cipher -> ba -> ba
|
||||||
ctrCombine = ctrCombineGeneric
|
ctrCombine = ctrCombineGeneric
|
||||||
|
|
||||||
|
-- | 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
|
||||||
|
|
||||||
|
-- | class of block cipher with a 128 bits block size
|
||||||
|
class BlockCipher cipher => BlockCipher128 cipher where
|
||||||
-- | encrypt using the XTS mode.
|
-- | encrypt using the XTS mode.
|
||||||
--
|
--
|
||||||
-- input need to be a multiple of the blocksize, and the cipher
|
-- input need to be a multiple of the blocksize, and the cipher
|
||||||
@ -105,7 +116,7 @@ class Cipher cipher => BlockCipher cipher where
|
|||||||
-> DataUnitOffset -- ^ Offset in the data unit in number of blocks
|
-> DataUnitOffset -- ^ Offset in the data unit in number of blocks
|
||||||
-> ByteString -- ^ Plaintext
|
-> ByteString -- ^ Plaintext
|
||||||
-> ByteString -- ^ Ciphertext
|
-> ByteString -- ^ Ciphertext
|
||||||
xtsEncrypt = xtsEncryptGeneric
|
xtsEncrypt = undefined -- xtsEncryptGeneric
|
||||||
|
|
||||||
-- | decrypt using the XTS mode.
|
-- | decrypt using the XTS mode.
|
||||||
--
|
--
|
||||||
@ -116,13 +127,7 @@ class Cipher cipher => BlockCipher cipher where
|
|||||||
-> DataUnitOffset -- ^ Offset in the data unit in number of blocks
|
-> DataUnitOffset -- ^ Offset in the data unit in number of blocks
|
||||||
-> ByteString -- ^ Ciphertext
|
-> ByteString -- ^ Ciphertext
|
||||||
-> ByteString -- ^ Plaintext
|
-> ByteString -- ^ Plaintext
|
||||||
xtsDecrypt = xtsDecryptGeneric
|
xtsDecrypt = undefined -- 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
|
-- | Authenticated Encryption with Associated Data algorithms
|
||||||
data AEAD cipher = AEAD cipher (AEADState cipher)
|
data AEAD cipher = AEAD cipher (AEADState cipher)
|
||||||
@ -156,6 +161,8 @@ nullIV = toIV undefined
|
|||||||
--
|
--
|
||||||
-- Assume the IV is in Big Endian format.
|
-- Assume the IV is in Big Endian format.
|
||||||
ivAdd :: BlockCipher c => IV c -> Int -> IV c
|
ivAdd :: BlockCipher c => IV c -> Int -> IV c
|
||||||
|
ivAdd i _ = i
|
||||||
|
{-
|
||||||
ivAdd (IV b) i = IV $ snd $ B.mapAccumR addCarry i b
|
ivAdd (IV b) i = IV $ snd $ B.mapAccumR addCarry i b
|
||||||
where addCarry :: Int -> Word8 -> (Int, Word8)
|
where addCarry :: Int -> Word8 -> (Int, Word8)
|
||||||
addCarry acc w
|
addCarry acc w
|
||||||
@ -163,49 +170,54 @@ ivAdd (IV b) i = IV $ snd $ B.mapAccumR addCarry i b
|
|||||||
| otherwise = let (hi,lo) = acc `divMod` 256
|
| otherwise = let (hi,lo) = acc `divMod` 256
|
||||||
nw = lo + (fromIntegral w)
|
nw = lo + (fromIntegral w)
|
||||||
in (hi + (nw `shiftR` 8), fromIntegral nw)
|
in (hi + (nw `shiftR` 8), fromIntegral nw)
|
||||||
|
-}
|
||||||
|
|
||||||
cbcEncryptGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString
|
cbcEncryptGeneric :: (ByteArray ba, BlockCipher cipher) => cipher -> IV cipher -> ba -> ba
|
||||||
cbcEncryptGeneric cipher (IV ivini) input = B.concat $ doEnc ivini $ chunk (blockSize cipher) input
|
cbcEncryptGeneric cipher ivini input = byteArrayConcat $ doEnc ivini $ chunk (blockSize cipher) input
|
||||||
where doEnc _ [] = []
|
where doEnc _ [] = []
|
||||||
doEnc iv (i:is) =
|
doEnc iv (i:is) =
|
||||||
let o = ecbEncrypt cipher $ bxor iv i
|
let o = ecbEncrypt cipher $ byteArrayXor iv i
|
||||||
in o : doEnc o is
|
in o : doEnc (IV o) is
|
||||||
|
|
||||||
cbcDecryptGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString
|
cbcDecryptGeneric :: (ByteArray ba, BlockCipher cipher) => cipher -> IV cipher -> ba -> ba
|
||||||
cbcDecryptGeneric cipher (IV ivini) input = B.concat $ doDec ivini $ chunk (blockSize cipher) input
|
cbcDecryptGeneric cipher ivini input = byteArrayConcat $ doDec ivini $ chunk (blockSize cipher) input
|
||||||
where doDec _ [] = []
|
where
|
||||||
|
doDec _ [] = []
|
||||||
doDec iv (i:is) =
|
doDec iv (i:is) =
|
||||||
let o = bxor iv $ ecbDecrypt cipher i
|
let o = byteArrayXor iv $ ecbDecrypt cipher i
|
||||||
in o : doDec i is
|
in o : doDec (IV i) is
|
||||||
|
|
||||||
cfbEncryptGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString
|
cfbEncryptGeneric :: (ByteArray ba, BlockCipher cipher) => cipher -> IV cipher -> ba -> ba
|
||||||
cfbEncryptGeneric cipher (IV ivini) input = B.concat $ doEnc ivini $ chunk (blockSize cipher) input
|
cfbEncryptGeneric cipher ivini input = byteArrayConcat $ doEnc ivini $ chunk (blockSize cipher) input
|
||||||
where doEnc _ [] = []
|
where
|
||||||
|
doEnc _ [] = []
|
||||||
doEnc iv (i:is) =
|
doEnc iv (i:is) =
|
||||||
let o = bxor i $ ecbEncrypt cipher iv
|
let o = byteArrayXor i $ ecbEncrypt cipher iv
|
||||||
in o : doEnc o is
|
in o : doEnc (IV o) is
|
||||||
|
|
||||||
cfbDecryptGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString
|
cfbDecryptGeneric :: (ByteArray ba, BlockCipher cipher) => cipher -> IV cipher -> ba -> ba
|
||||||
cfbDecryptGeneric cipher (IV ivini) input = B.concat $ doDec ivini $ chunk (blockSize cipher) input
|
cfbDecryptGeneric cipher ivini input = byteArrayConcat $ doDec ivini $ chunk (blockSize cipher) input
|
||||||
where doDec _ [] = []
|
where
|
||||||
|
doDec _ [] = []
|
||||||
doDec iv (i:is) =
|
doDec iv (i:is) =
|
||||||
let o = bxor i $ ecbEncrypt cipher iv
|
let o = byteArrayXor i $ ecbEncrypt cipher iv
|
||||||
in o : doDec i is
|
in o : doDec (IV i) is
|
||||||
|
|
||||||
ctrCombineGeneric :: BlockCipher cipher => cipher -> IV cipher -> ByteString -> ByteString
|
ctrCombineGeneric :: (ByteArray ba, BlockCipher cipher) => cipher -> IV cipher -> ba -> ba
|
||||||
ctrCombineGeneric cipher ivini input = B.concat $ doCnt ivini $ chunk (blockSize cipher) input
|
ctrCombineGeneric cipher ivini input = byteArrayConcat $ doCnt ivini $ chunk (blockSize cipher) input
|
||||||
where doCnt _ [] = []
|
where doCnt _ [] = []
|
||||||
doCnt iv (i:is) =
|
doCnt iv (i:is) =
|
||||||
let ivEnc = ecbEncrypt cipher (toBytes iv)
|
let ivEnc = ecbEncrypt cipher iv
|
||||||
in bxor i ivEnc : doCnt (ivAdd iv 1) is
|
in byteArrayXor i ivEnc : doCnt (ivAdd iv 1) is
|
||||||
|
|
||||||
xtsEncryptGeneric :: BlockCipher cipher => XTS cipher
|
{-
|
||||||
|
xtsEncryptGeneric :: BlockCipher128 cipher => XTS cipher
|
||||||
xtsEncryptGeneric = xtsGeneric ecbEncrypt
|
xtsEncryptGeneric = xtsGeneric ecbEncrypt
|
||||||
|
|
||||||
xtsDecryptGeneric :: BlockCipher cipher => XTS cipher
|
xtsDecryptGeneric :: BlockCipher128 cipher => XTS cipher
|
||||||
xtsDecryptGeneric = xtsGeneric ecbDecrypt
|
xtsDecryptGeneric = xtsGeneric ecbDecrypt
|
||||||
|
|
||||||
xtsGeneric :: BlockCipher cipher
|
xtsGeneric :: BlockCipher128 cipher
|
||||||
=> (cipher -> B.ByteString -> B.ByteString)
|
=> (cipher -> B.ByteString -> B.ByteString)
|
||||||
-> (cipher, cipher)
|
-> (cipher, cipher)
|
||||||
-> IV cipher
|
-> IV cipher
|
||||||
@ -214,14 +226,16 @@ xtsGeneric :: BlockCipher cipher
|
|||||||
-> ByteString
|
-> ByteString
|
||||||
xtsGeneric f (cipher, tweakCipher) iv sPoint input
|
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"
|
| 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
|
| otherwise = byteArrayConcat $ doXts iniTweak $ chunk (blockSize cipher) input
|
||||||
where encTweak = ecbEncrypt tweakCipher (toBytes iv)
|
where encTweak = ecbEncrypt tweakCipher iv
|
||||||
iniTweak = iterate xtsGFMul encTweak !! fromIntegral sPoint
|
iniTweak = iterate xtsGFMul encTweak !! fromIntegral sPoint
|
||||||
doXts _ [] = []
|
doXts _ [] = []
|
||||||
doXts tweak (i:is) =
|
doXts tweak (i:is) =
|
||||||
let o = bxor (f cipher $ bxor i tweak) tweak
|
let o = bxor (f cipher $ bxor i tweak) tweak
|
||||||
in o : doXts (xtsGFMul tweak) is
|
in o : doXts (xtsGFMul tweak) is
|
||||||
|
-}
|
||||||
|
|
||||||
|
{-
|
||||||
-- | Encrypt using CFB mode in 8 bit output
|
-- | Encrypt using CFB mode in 8 bit output
|
||||||
--
|
--
|
||||||
-- Effectively turn a Block cipher in CFB mode into a Stream cipher
|
-- Effectively turn a Block cipher in CFB mode into a Stream cipher
|
||||||
@ -251,3 +265,4 @@ cfb8Decrypt ctx origIv msg = B.unsafeCreate (B.length msg) $ \dst -> loop dst or
|
|||||||
r = cfbDecrypt ctx iv m'
|
r = cfbDecrypt ctx iv m'
|
||||||
out = B.head r
|
out = B.head r
|
||||||
ni = IV (B.drop 1 i `B.snoc` B.head m')
|
ni = IV (B.drop 1 i `B.snoc` B.head m')
|
||||||
|
-}
|
||||||
|
|||||||
@ -9,16 +9,11 @@
|
|||||||
--
|
--
|
||||||
module Crypto.Cipher.Types.Utils where
|
module Crypto.Cipher.Types.Utils where
|
||||||
|
|
||||||
import Data.Bits (xor)
|
import Crypto.Internal.ByteArray
|
||||||
import Data.ByteString (ByteString)
|
|
||||||
import qualified Data.ByteString as B
|
|
||||||
|
|
||||||
chunk :: Int -> ByteString -> [ByteString]
|
chunk :: ByteArray b => Int -> b -> [b]
|
||||||
chunk sz bs = split bs
|
chunk sz bs = split bs
|
||||||
where split b | B.length b <= sz = [b]
|
where split b | byteArrayLength b <= sz = [b]
|
||||||
| otherwise =
|
| otherwise =
|
||||||
let (b1, b2) = B.splitAt sz b
|
let (b1, b2) = byteArraySplit sz b
|
||||||
in b1 : split b2
|
in b1 : split b2
|
||||||
|
|
||||||
bxor :: ByteString -> ByteString -> ByteString
|
|
||||||
bxor src dst = B.pack $ B.zipWith xor src dst
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user