{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
{-# LANGUAGE ParallelListComp #-}
module Crypto.Classes
(
Hash(..)
, hashFunc'
, hashFunc
, BlockCipher(..)
, blockSizeBytes
, keyLengthBytes
, buildKeyIO
, buildKeyGen
, StreamCipher(..)
, buildStreamKeyIO
, buildStreamKeyGen
, AsymCipher(..)
, buildKeyPairIO
, buildKeyPairGen
, Signing(..)
, buildSigningKeyPairIO
, buildSigningKeyPairGen
, encode
, zeroIV
, incIV
, getIV, getIVIO
, chunkFor, chunkFor'
, module Crypto.Util
, module Crypto.Types
) where
import Data.Data
import Data.Typeable
import Data.Serialize
import qualified Data.Serialize.Get as SG
import qualified Data.Serialize.Put as SP
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as I
import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.State (StateT(..), runStateT)
import Control.Monad (liftM)
import Data.Bits
import Data.List (foldl', genericDrop)
import Data.Word (Word8, Word16, Word64)
import Data.Tagged
import Data.Proxy
import Crypto.Types
import Crypto.Random
import Crypto.Util
import System.IO.Unsafe (unsafePerformIO)
import Foreign (Ptr)
import Foreign.C (CChar(..), CInt(..))
import System.Entropy
import {-# SOURCE #-} Crypto.Modes
class (Serialize d, Eq d, Ord d)
=> Hash ctx d | d -> ctx, ctx -> d where
outputLength :: Tagged d BitLength
blockLength :: Tagged d BitLength
initialCtx :: ctx
updateCtx :: ctx -> B.ByteString -> ctx
finalize :: ctx -> B.ByteString -> d
hash :: (Hash ctx d) => L.ByteString -> d
hash ByteString
msg = d
res
where
res :: d
res = forall ctx d. Hash ctx d => ctx -> ByteString -> d
finalize ctx
ctx ByteString
end
ctx :: ctx
ctx = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' forall ctx d. Hash ctx d => ctx -> ByteString -> ctx
updateCtx forall ctx d. Hash ctx d => ctx
initialCtx [ByteString]
blks
([ByteString]
blks,ByteString
end) = ByteString -> Int -> ([ByteString], ByteString)
makeBlocks ByteString
msg Int
blockLen
blockLen :: Int
blockLen = (forall ctx d. Hash ctx d => Tagged d Int
blockLength forall a b. Tagged a b -> a -> b
.::. d
res) forall a. Integral a => a -> a -> a
`div` Int
8
hash' :: (Hash ctx d) => B.ByteString -> d
hash' ByteString
msg = d
res
where
res :: d
res = forall ctx d. Hash ctx d => ctx -> ByteString -> d
finalize (forall ctx d. Hash ctx d => ctx -> ByteString -> ctx
updateCtx forall ctx d. Hash ctx d => ctx
initialCtx ByteString
top) ByteString
end
(ByteString
top, ByteString
end) = Int -> ByteString -> (ByteString, ByteString)
B.splitAt Int
remlen ByteString
msg
remlen :: Int
remlen = ByteString -> Int
B.length ByteString
msg forall a. Num a => a -> a -> a
- (ByteString -> Int
B.length ByteString
msg forall a. Integral a => a -> a -> a
`rem` Int
bLen)
bLen :: Int
bLen = forall ctx d. Hash ctx d => Tagged d Int
blockLength forall a b. Tagged a b -> a -> b
`for` d
res forall a. Integral a => a -> a -> a
`div` Int
8
hashFunc :: Hash c d => d -> (L.ByteString -> d)
hashFunc :: forall c d. Hash c d => d -> ByteString -> d
hashFunc d
d = ByteString -> d
f
where
f :: ByteString -> d
f = forall ctx d. (Hash ctx d, Hash ctx d) => ByteString -> d
hash
a :: d
a = ByteString -> d
f forall a. HasCallStack => a
undefined forall a. a -> a -> a
`asTypeOf` d
d
hashFunc' :: Hash c d => d -> (B.ByteString -> d)
hashFunc' :: forall c d. Hash c d => d -> ByteString -> d
hashFunc' d
d = ByteString -> d
f
where
f :: ByteString -> d
f = forall ctx d. (Hash ctx d, Hash ctx d) => ByteString -> d
hash'
a :: d
a = ByteString -> d
f forall a. HasCallStack => a
undefined forall a. a -> a -> a
`asTypeOf` d
d
{-# INLINABLE makeBlocks #-}
makeBlocks :: L.ByteString -> ByteLength -> ([B.ByteString], B.ByteString)
makeBlocks :: ByteString -> Int -> ([ByteString], ByteString)
makeBlocks ByteString
msg Int
len = [ByteString] -> ([ByteString], ByteString)
go (ByteString -> [ByteString]
L.toChunks ByteString
msg)
where
go :: [ByteString] -> ([ByteString], ByteString)
go [] = ([],ByteString
B.empty)
go (ByteString
x:[ByteString]
xs)
| ByteString -> Int
B.length ByteString
x forall a. Ord a => a -> a -> Bool
>= Int
len =
let l :: Int
l = ByteString -> Int
B.length ByteString
x forall a. Num a => a -> a -> a
- ByteString -> Int
B.length ByteString
x forall a. Integral a => a -> a -> a
`rem` Int
len
(ByteString
top,ByteString
end) = Int -> ByteString -> (ByteString, ByteString)
B.splitAt Int
l ByteString
x
([ByteString]
rest,ByteString
trueEnd) = [ByteString] -> ([ByteString], ByteString)
go (ByteString
endforall a. a -> [a] -> [a]
:[ByteString]
xs)
in (ByteString
topforall a. a -> [a] -> [a]
:[ByteString]
rest, ByteString
trueEnd)
| Bool
otherwise =
case [ByteString]
xs of
[] -> ([], ByteString
x)
(ByteString
a:[ByteString]
as) -> [ByteString] -> ([ByteString], ByteString)
go (ByteString -> ByteString -> ByteString
B.append ByteString
x ByteString
a forall a. a -> [a] -> [a]
: [ByteString]
as)
class ( Serialize k) => BlockCipher k where
blockSize :: Tagged k BitLength
encryptBlock :: k -> B.ByteString -> B.ByteString
decryptBlock :: k -> B.ByteString -> B.ByteString
buildKey :: B.ByteString -> Maybe k
keyLength :: Tagged k BitLength
ecb :: k -> B.ByteString -> B.ByteString
ecb = forall k. BlockCipher k => k -> ByteString -> ByteString
modeEcb'
unEcb :: k -> B.ByteString -> B.ByteString
unEcb = forall k. BlockCipher k => k -> ByteString -> ByteString
modeUnEcb'
cbc :: k -> IV k -> B.ByteString -> (B.ByteString, IV k)
cbc = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeCbc'
unCbc :: k -> IV k -> B.ByteString -> (B.ByteString, IV k)
unCbc = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCbc'
ctr :: k -> IV k -> B.ByteString -> (B.ByteString, IV k)
ctr = forall k.
BlockCipher k =>
(IV k -> IV k) -> k -> IV k -> ByteString -> (ByteString, IV k)
modeCtr' forall k. BlockCipher k => IV k -> IV k
incIV
unCtr :: k -> IV k -> B.ByteString -> (B.ByteString, IV k)
unCtr = forall k.
BlockCipher k =>
(IV k -> IV k) -> k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCtr' forall k. BlockCipher k => IV k -> IV k
incIV
ctrLazy :: k -> IV k -> L.ByteString -> (L.ByteString, IV k)
ctrLazy = forall k.
BlockCipher k =>
(IV k -> IV k) -> k -> IV k -> ByteString -> (ByteString, IV k)
modeCtr forall k. BlockCipher k => IV k -> IV k
incIV
unCtrLazy :: k -> IV k -> L.ByteString -> (L.ByteString, IV k)
unCtrLazy = forall k.
BlockCipher k =>
(IV k -> IV k) -> k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCtr forall k. BlockCipher k => IV k -> IV k
incIV
cfb :: k -> IV k -> B.ByteString -> (B.ByteString, IV k)
cfb = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeCfb'
unCfb :: k -> IV k -> B.ByteString -> (B.ByteString, IV k)
unCfb = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCfb'
ofb :: k -> IV k -> B.ByteString -> (B.ByteString, IV k)
ofb = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeOfb'
unOfb :: k -> IV k -> B.ByteString -> (B.ByteString, IV k)
unOfb = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnOfb'
cbcLazy :: k -> IV k -> L.ByteString -> (L.ByteString, IV k)
cbcLazy = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeCbc
unCbcLazy :: k -> IV k -> L.ByteString -> (L.ByteString, IV k)
unCbcLazy = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCbc
sivLazy :: k -> k -> [L.ByteString] -> L.ByteString -> Maybe L.ByteString
sivLazy = forall k.
BlockCipher k =>
k -> k -> [ByteString] -> ByteString -> Maybe ByteString
modeSiv
unSivLazy :: k -> k -> [L.ByteString] -> L.ByteString -> Maybe L.ByteString
unSivLazy = forall k.
BlockCipher k =>
k -> k -> [ByteString] -> ByteString -> Maybe ByteString
modeUnSiv
siv :: k -> k -> [B.ByteString] -> B.ByteString -> Maybe B.ByteString
siv = forall k.
BlockCipher k =>
k -> k -> [ByteString] -> ByteString -> Maybe ByteString
modeSiv'
unSiv :: k -> k -> [B.ByteString] -> B.ByteString -> Maybe B.ByteString
unSiv = forall k.
BlockCipher k =>
k -> k -> [ByteString] -> ByteString -> Maybe ByteString
modeUnSiv'
ecbLazy :: k -> L.ByteString -> L.ByteString
ecbLazy = forall k. BlockCipher k => k -> ByteString -> ByteString
modeEcb
unEcbLazy :: k -> L.ByteString -> L.ByteString
unEcbLazy = forall k. BlockCipher k => k -> ByteString -> ByteString
modeUnEcb
cfbLazy :: k -> IV k -> L.ByteString -> (L.ByteString, IV k)
cfbLazy = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeCfb
unCfbLazy :: k -> IV k -> L.ByteString -> (L.ByteString, IV k)
unCfbLazy = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCfb
ofbLazy :: k -> IV k -> L.ByteString -> (L.ByteString, IV k)
ofbLazy = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeOfb
unOfbLazy :: k -> IV k -> L.ByteString -> (L.ByteString, IV k)
unOfbLazy = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnOfb
modeOfb :: BlockCipher k => k -> IV k -> L.ByteString -> (L.ByteString, IV k)
modeOfb :: forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeOfb = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnOfb
{-# INLINEABLE modeOfb #-}
modeUnOfb :: BlockCipher k => k -> IV k -> L.ByteString -> (L.ByteString, IV k)
modeUnOfb :: forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnOfb k
k (IV ByteString
iv) ByteString
msg =
let ivStr :: [ByteString]
ivStr = forall a. Int -> [a] -> [a]
drop Int
1 (forall a. (a -> a) -> a -> [a]
iterate (forall k. BlockCipher k => k -> ByteString -> ByteString
encryptBlock k
k) ByteString
iv)
ivLen :: Int64
ivLen = forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
B.length ByteString
iv)
newIV :: IV k
newIV = forall k. ByteString -> IV k
IV forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
B.concat forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int64 -> ByteString -> ByteString
L.take Int64
ivLen forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int64 -> ByteString -> ByteString
L.drop (ByteString -> Int64
L.length ByteString
msg) forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
L.fromChunks forall a b. (a -> b) -> a -> b
$ [ByteString]
ivStr
in (ByteString -> ByteString -> ByteString
zwp ([ByteString] -> ByteString
L.fromChunks [ByteString]
ivStr) ByteString
msg, forall {k}. IV k
newIV)
{-# INLINEABLE modeUnOfb #-}
modeCfb :: BlockCipher k => k -> IV k -> L.ByteString -> (L.ByteString, IV k)
modeCfb :: forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeCfb k
k (IV ByteString
v) ByteString
msg =
let blks :: [ByteString]
blks = forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor k
k ByteString
msg
([ByteString]
cs,ByteString
ivF) = ByteString -> [ByteString] -> ([ByteString], ByteString)
go ByteString
v [ByteString]
blks
in ([ByteString] -> ByteString
L.fromChunks [ByteString]
cs, forall k. ByteString -> IV k
IV ByteString
ivF)
where
go :: ByteString -> [ByteString] -> ([ByteString], ByteString)
go ByteString
iv [] = ([],ByteString
iv)
go ByteString
iv (ByteString
b:[ByteString]
bs) =
let c :: ByteString
c = ByteString -> ByteString -> ByteString
zwp' (forall k. BlockCipher k => k -> ByteString -> ByteString
encryptBlock k
k ByteString
iv) ByteString
b
([ByteString]
cs,ByteString
ivFinal) = ByteString -> [ByteString] -> ([ByteString], ByteString)
go ByteString
c [ByteString]
bs
in (ByteString
cforall a. a -> [a] -> [a]
:[ByteString]
cs, ByteString
ivFinal)
{-# INLINEABLE modeCfb #-}
modeUnCfb :: BlockCipher k => k -> IV k -> L.ByteString -> (L.ByteString, IV k)
modeUnCfb :: forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCfb k
k (IV ByteString
v) ByteString
msg =
let blks :: [ByteString]
blks = forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor k
k ByteString
msg
([ByteString]
ps, ByteString
ivF) = ByteString -> [ByteString] -> ([ByteString], ByteString)
go ByteString
v [ByteString]
blks
in ([ByteString] -> ByteString
L.fromChunks [ByteString]
ps, forall k. ByteString -> IV k
IV ByteString
ivF)
where
go :: ByteString -> [ByteString] -> ([ByteString], ByteString)
go ByteString
iv [] = ([], ByteString
iv)
go ByteString
iv (ByteString
b:[ByteString]
bs) =
let p :: ByteString
p = ByteString -> ByteString -> ByteString
zwp' (forall k. BlockCipher k => k -> ByteString -> ByteString
encryptBlock k
k ByteString
iv) ByteString
b
([ByteString]
ps, ByteString
ivF) = ByteString -> [ByteString] -> ([ByteString], ByteString)
go ByteString
b [ByteString]
bs
in (ByteString
pforall a. a -> [a] -> [a]
:[ByteString]
ps, ByteString
ivF)
{-# INLINEABLE modeUnCfb #-}
getIV :: (BlockCipher k, CryptoRandomGen g) => g -> Either GenError (IV k, g)
getIV :: forall k g.
(BlockCipher k, CryptoRandomGen g) =>
g -> Either GenError (IV k, g)
getIV g
g =
let bytes :: Int
bytes = forall k. BlockCipher k => IV k -> Int
ivBlockSizeBytes IV k
iv
gen :: Either GenError (ByteString, g)
gen = forall g.
CryptoRandomGen g =>
Int -> g -> Either GenError (ByteString, g)
genBytes Int
bytes g
g
fromRight :: Either a b -> b
fromRight (Right b
x) = b
x
iv :: IV k
iv = forall k. ByteString -> IV k
IV (forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a} {b}. Either a b -> b
fromRight forall a b. (a -> b) -> a -> b
$ Either GenError (ByteString, g)
gen)
in case Either GenError (ByteString, g)
gen of
Left GenError
err -> forall a b. a -> Either a b
Left GenError
err
Right (ByteString
bs,g
g')
| ByteString -> Int
B.length ByteString
bs forall a. Eq a => a -> a -> Bool
== Int
bytes -> forall a b. b -> Either a b
Right (IV k
iv, g
g')
| Bool
otherwise -> forall a b. a -> Either a b
Left (String -> GenError
GenErrorOther String
"Generator failed to provide requested number of bytes")
{-# INLINEABLE getIV #-}
getIVIO :: (BlockCipher k) => IO (IV k)
getIVIO :: forall k. BlockCipher k => IO (IV k)
getIVIO = do
let p :: Proxy t
p = forall {k} (t :: k). Proxy t
Proxy
getTypedIV :: BlockCipher k => Proxy k -> IO (IV k)
getTypedIV :: forall k. BlockCipher k => Proxy k -> IO (IV k)
getTypedIV Proxy k
pr = forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM forall k. ByteString -> IV k
IV (Int -> IO ByteString
getEntropy (forall {k} (s :: k) a (proxy :: k -> *). Tagged s a -> proxy s -> a
proxy forall k. BlockCipher k => Tagged k Int
blockSize Proxy k
pr forall a. Integral a => a -> a -> a
`div` Int
8))
IV k
iv <- forall k. BlockCipher k => Proxy k -> IO (IV k)
getTypedIV forall {t}. Proxy t
p
forall (m :: * -> *) a. Monad m => a -> m a
return (IV k
iv forall a (proxy :: * -> *). a -> proxy a -> a
`asProxyTypeOf` forall k. Proxy k -> Proxy (IV k)
ivProxy forall {t}. Proxy t
p)
{-# INLINEABLE getIVIO #-}
ivProxy :: Proxy k -> Proxy (IV k)
ivProxy :: forall k. Proxy k -> Proxy (IV k)
ivProxy = forall a b. a -> b -> a
const forall {k} (t :: k). Proxy t
Proxy
deIVProxy :: Proxy (IV k) -> Proxy k
deIVProxy :: forall k. Proxy (IV k) -> Proxy k
deIVProxy = forall a b. a -> b -> a
const forall {k} (t :: k). Proxy t
Proxy
modeEcb :: BlockCipher k => k -> L.ByteString -> L.ByteString
modeEcb :: forall k. BlockCipher k => k -> ByteString -> ByteString
modeEcb k
k ByteString
msg =
let chunks :: [ByteString]
chunks = forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor k
k ByteString
msg
in [ByteString] -> ByteString
L.fromChunks forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall k. BlockCipher k => k -> ByteString -> ByteString
encryptBlock k
k) [ByteString]
chunks
{-# INLINEABLE modeEcb #-}
modeUnEcb :: BlockCipher k => k -> L.ByteString -> L.ByteString
modeUnEcb :: forall k. BlockCipher k => k -> ByteString -> ByteString
modeUnEcb k
k ByteString
msg =
let chunks :: [ByteString]
chunks = forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor k
k ByteString
msg
in [ByteString] -> ByteString
L.fromChunks forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall k. BlockCipher k => k -> ByteString -> ByteString
decryptBlock k
k) [ByteString]
chunks
{-# INLINEABLE modeUnEcb #-}
modeSiv :: BlockCipher k => k -> k -> [L.ByteString] -> L.ByteString -> Maybe L.ByteString
modeSiv :: forall k.
BlockCipher k =>
k -> k -> [ByteString] -> ByteString -> Maybe ByteString
modeSiv k
k1 k
k2 [ByteString]
xs ByteString
m
| forall (t :: * -> *) a. Foldable t => t a -> Int
length [ByteString]
xs forall a. Ord a => a -> a -> Bool
> Int
bSizeb forall a. Num a => a -> a -> a
- Int
1 = forall a. Maybe a
Nothing
| Bool
otherwise = forall a. a -> Maybe a
Just
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString -> ByteString
L.append ByteString
iv
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
ctrLazy k
k2 (forall k. ByteString -> IV k
IV forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
sivMask forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
B.concat forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks forall a b. (a -> b) -> a -> b
$ ByteString
iv)
forall a b. (a -> b) -> a -> b
$ ByteString
m
where
bSize :: Integer
bSize = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall k. BlockCipher k => Tagged k Int
blockSizeBytes forall a b. Tagged a b -> a -> b
`for` k
k1
bSizeb :: Int
bSizeb = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall k. BlockCipher k => Tagged k Int
blockSize forall a b. Tagged a b -> a -> b
`for` k
k1
iv :: ByteString
iv = forall k. BlockCipher k => k -> [ByteString] -> ByteString
cMacStar k
k1 forall a b. (a -> b) -> a -> b
$ [ByteString]
xs forall a. [a] -> [a] -> [a]
++ [ByteString
m]
modeUnSiv :: BlockCipher k => k -> k -> [L.ByteString] -> L.ByteString -> Maybe L.ByteString
modeUnSiv :: forall k.
BlockCipher k =>
k -> k -> [ByteString] -> ByteString -> Maybe ByteString
modeUnSiv k
k1 k
k2 [ByteString]
xs ByteString
c | forall (t :: * -> *) a. Foldable t => t a -> Int
length [ByteString]
xs forall a. Ord a => a -> a -> Bool
> Int
bSizeb forall a. Num a => a -> a -> a
- Int
1 = forall a. Maybe a
Nothing
| ByteString -> Int64
L.length ByteString
c forall a. Ord a => a -> a -> Bool
< forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
bSize = forall a. Maybe a
Nothing
| ByteString
iv forall a. Eq a => a -> a -> Bool
/= (forall k. BlockCipher k => k -> [ByteString] -> ByteString
cMacStar k
k1 forall a b. (a -> b) -> a -> b
$ [ByteString]
xs forall a. [a] -> [a] -> [a]
++ [ByteString
dm]) = forall a. Maybe a
Nothing
| Bool
otherwise = forall a. a -> Maybe a
Just ByteString
dm
where
bSize :: Integer
bSize = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall k. BlockCipher k => Tagged k Int
blockSizeBytes forall a b. Tagged a b -> a -> b
`for` k
k1
bSizeb :: Int
bSizeb = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall k. BlockCipher k => Tagged k Int
blockSize forall a b. Tagged a b -> a -> b
`for` k
k1
(ByteString
iv,ByteString
m) = Int64 -> ByteString -> (ByteString, ByteString)
L.splitAt (forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
bSize) ByteString
c
dm :: ByteString
dm = forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall k.
BlockCipher k =>
(IV k -> IV k) -> k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCtr forall k. BlockCipher k => IV k -> IV k
incIV k
k2 (forall k. ByteString -> IV k
IV forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
sivMask forall a b. (a -> b) -> a -> b
$ [ByteString] -> ByteString
B.concat forall a b. (a -> b) -> a -> b
$ ByteString -> [ByteString]
L.toChunks ByteString
iv) ByteString
m
modeSiv' :: BlockCipher k => k -> k -> [B.ByteString] -> B.ByteString -> Maybe B.ByteString
modeSiv' :: forall k.
BlockCipher k =>
k -> k -> [ByteString] -> ByteString -> Maybe ByteString
modeSiv' k
k1 k
k2 [ByteString]
xs ByteString
m | forall (t :: * -> *) a. Foldable t => t a -> Int
length [ByteString]
xs forall a. Ord a => a -> a -> Bool
> Int
bSizeb forall a. Num a => a -> a -> a
- Int
1 = forall a. Maybe a
Nothing
| Bool
otherwise = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString -> ByteString
B.append ByteString
iv forall a b. (a -> b) -> a -> b
$ forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
Crypto.Classes.ctr k
k2 (forall k. ByteString -> IV k
IV forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
sivMask ByteString
iv) ByteString
m
where
bSize :: Integer
bSize = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall k. BlockCipher k => Tagged k Int
blockSizeBytes forall a b. Tagged a b -> a -> b
`for` k
k1
bSizeb :: Int
bSizeb = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall k. BlockCipher k => Tagged k Int
blockSize forall a b. Tagged a b -> a -> b
`for` k
k1
iv :: ByteString
iv = forall k. BlockCipher k => k -> [ByteString] -> ByteString
cMacStar' k
k1 forall a b. (a -> b) -> a -> b
$ [ByteString]
xs forall a. [a] -> [a] -> [a]
++ [ByteString
m]
modeUnSiv' :: BlockCipher k => k -> k -> [B.ByteString] -> B.ByteString -> Maybe B.ByteString
modeUnSiv' :: forall k.
BlockCipher k =>
k -> k -> [ByteString] -> ByteString -> Maybe ByteString
modeUnSiv' k
k1 k
k2 [ByteString]
xs ByteString
c | forall (t :: * -> *) a. Foldable t => t a -> Int
length [ByteString]
xs forall a. Ord a => a -> a -> Bool
> Int
bSizeb forall a. Num a => a -> a -> a
- Int
1 = forall a. Maybe a
Nothing
| ByteString -> Int
B.length ByteString
c forall a. Ord a => a -> a -> Bool
< Int
bSize = forall a. Maybe a
Nothing
| ByteString
iv forall a. Eq a => a -> a -> Bool
/= (forall k. BlockCipher k => k -> [ByteString] -> ByteString
cMacStar' k
k1 forall a b. (a -> b) -> a -> b
$ [ByteString]
xs forall a. [a] -> [a] -> [a]
++ [ByteString
dm]) = forall a. Maybe a
Nothing
| Bool
otherwise = forall a. a -> Maybe a
Just ByteString
dm
where
bSize :: Int
bSize = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall k. BlockCipher k => Tagged k Int
blockSizeBytes forall a b. Tagged a b -> a -> b
`for` k
k1
bSizeb :: Int
bSizeb = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall k. BlockCipher k => Tagged k Int
blockSize forall a b. Tagged a b -> a -> b
`for` k
k1
(ByteString
iv,ByteString
m) = Int -> ByteString -> (ByteString, ByteString)
B.splitAt Int
bSize ByteString
c
dm :: ByteString
dm = forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
Crypto.Classes.unCtr k
k2 (forall k. ByteString -> IV k
IV forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
sivMask ByteString
iv) ByteString
m
modeCbc :: BlockCipher k => k -> IV k -> L.ByteString -> (L.ByteString, IV k)
modeCbc :: forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeCbc k
k (IV ByteString
v) ByteString
plaintext =
let blks :: [ByteString]
blks = forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor k
k ByteString
plaintext
([ByteString]
cts, ByteString
iv) = [ByteString] -> ByteString -> ([ByteString], ByteString)
go [ByteString]
blks ByteString
v
in ([ByteString] -> ByteString
L.fromChunks [ByteString]
cts, forall k. ByteString -> IV k
IV ByteString
iv)
where
go :: [ByteString] -> ByteString -> ([ByteString], ByteString)
go [] ByteString
iv = ([], ByteString
iv)
go (ByteString
b:[ByteString]
bs) ByteString
iv =
let c :: ByteString
c = forall k. BlockCipher k => k -> ByteString -> ByteString
encryptBlock k
k (ByteString -> ByteString -> ByteString
zwp' ByteString
iv ByteString
b)
([ByteString]
cs, ByteString
ivFinal) = [ByteString] -> ByteString -> ([ByteString], ByteString)
go [ByteString]
bs ByteString
c
in (ByteString
cforall a. a -> [a] -> [a]
:[ByteString]
cs, ByteString
ivFinal)
{-# INLINEABLE modeCbc #-}
modeUnCbc :: BlockCipher k => k -> IV k -> L.ByteString -> (L.ByteString, IV k)
modeUnCbc :: forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCbc k
k (IV ByteString
v) ByteString
ciphertext =
let blks :: [ByteString]
blks = forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor k
k ByteString
ciphertext
([ByteString]
pts, ByteString
iv) = [ByteString] -> ByteString -> ([ByteString], ByteString)
go [ByteString]
blks ByteString
v
in ([ByteString] -> ByteString
L.fromChunks [ByteString]
pts, forall k. ByteString -> IV k
IV ByteString
iv)
where
go :: [ByteString] -> ByteString -> ([ByteString], ByteString)
go [] ByteString
iv = ([], ByteString
iv)
go (ByteString
c:[ByteString]
cs) ByteString
iv =
let p :: ByteString
p = ByteString -> ByteString -> ByteString
zwp' (forall k. BlockCipher k => k -> ByteString -> ByteString
decryptBlock k
k ByteString
c) ByteString
iv
([ByteString]
ps, ByteString
ivFinal) = [ByteString] -> ByteString -> ([ByteString], ByteString)
go [ByteString]
cs ByteString
c
in (ByteString
pforall a. a -> [a] -> [a]
:[ByteString]
ps, ByteString
ivFinal)
{-# INLINEABLE modeUnCbc #-}
modeCtr :: BlockCipher k => (IV k -> IV k) -> k -> IV k -> L.ByteString -> (L.ByteString, IV k)
modeCtr :: forall k.
BlockCipher k =>
(IV k -> IV k) -> k -> IV k -> ByteString -> (ByteString, IV k)
modeCtr = forall k.
BlockCipher k =>
(IV k -> IV k) -> k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCtr
modeUnCtr :: BlockCipher k => (IV k -> IV k) -> k -> IV k -> L.ByteString -> (L.ByteString, IV k)
modeUnCtr :: forall k.
BlockCipher k =>
(IV k -> IV k) -> k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCtr IV k -> IV k
f k
k (IV ByteString
iv) ByteString
msg =
let ivStr :: [IV k]
ivStr = forall a. (a -> a) -> a -> [a]
iterate IV k -> IV k
f forall a b. (a -> b) -> a -> b
$ forall k. ByteString -> IV k
IV ByteString
iv
ivLen :: Int64
ivLen = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ ByteString -> Int
B.length ByteString
iv
newIV :: IV k
newIV = forall a. [a] -> a
head forall a b. (a -> b) -> a -> b
$ forall i a. Integral i => i -> [a] -> [a]
genericDrop ((Int64
ivLen forall a. Num a => a -> a -> a
- Int64
1 forall a. Num a => a -> a -> a
+ ByteString -> Int64
L.length ByteString
msg) forall a. Integral a => a -> a -> a
`div` Int64
ivLen) [IV k]
ivStr
in (ByteString -> ByteString -> ByteString
zwp ([ByteString] -> ByteString
L.fromChunks forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall k. BlockCipher k => k -> ByteString -> ByteString
encryptBlock k
k) forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall k. IV k -> ByteString
initializationVector [IV k]
ivStr) ByteString
msg, IV k
newIV)
blockSizeBytes :: (BlockCipher k) => Tagged k ByteLength
blockSizeBytes :: forall k. BlockCipher k => Tagged k Int
blockSizeBytes = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. Integral a => a -> a -> a
`div` Int
8) forall k. BlockCipher k => Tagged k Int
blockSize
keyLengthBytes :: (BlockCipher k) => Tagged k ByteLength
keyLengthBytes :: forall k. BlockCipher k => Tagged k Int
keyLengthBytes = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. Integral a => a -> a -> a
`div` Int
8) forall k. BlockCipher k => Tagged k Int
keyLength
buildKeyIO :: (BlockCipher k) => IO k
buildKeyIO :: forall k. BlockCipher k => IO k
buildKeyIO = forall k (m :: * -> *).
(BlockCipher k, Monad m) =>
(Int -> m ByteString) -> (String -> m k) -> m k
buildKeyM Int -> IO ByteString
getEntropy forall (m :: * -> *) a. MonadFail m => String -> m a
fail
buildKeyGen :: (BlockCipher k, CryptoRandomGen g) => g -> Either GenError (k, g)
buildKeyGen :: forall k g.
(BlockCipher k, CryptoRandomGen g) =>
g -> Either GenError (k, g)
buildKeyGen = forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT (forall k (m :: * -> *).
(BlockCipher k, Monad m) =>
(Int -> m ByteString) -> (String -> m k) -> m k
buildKeyM (forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall g.
CryptoRandomGen g =>
Int -> g -> Either GenError (ByteString, g)
genBytes) (forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> Either a b
Left forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> GenError
GenErrorOther))
buildKeyM :: (BlockCipher k, Monad m) => (Int -> m B.ByteString) -> (String -> m k) -> m k
buildKeyM :: forall k (m :: * -> *).
(BlockCipher k, Monad m) =>
(Int -> m ByteString) -> (String -> m k) -> m k
buildKeyM Int -> m ByteString
getMore String -> m k
err = forall {t}. (Eq t, Num t) => t -> m k
go (Int
0::Int)
where
go :: t -> m k
go t
1000 = String -> m k
err String
"Tried 1000 times to generate a key from the system entropy.\
\ No keys were returned! Perhaps the system entropy is broken\
\ or perhaps the BlockCipher instance being used has a non-flat\
\ keyspace."
go t
i = do
let bs :: Tagged k Int
bs = forall k. BlockCipher k => Tagged k Int
keyLength
ByteString
kd <- Int -> m ByteString
getMore ((Int
7 forall a. Num a => a -> a -> a
+ forall {k} (s :: k) b. Tagged s b -> b
untag Tagged k Int
bs) forall a. Integral a => a -> a -> a
`div` Int
8)
case forall k. BlockCipher k => ByteString -> Maybe k
buildKey ByteString
kd of
Maybe k
Nothing -> t -> m k
go (t
iforall a. Num a => a -> a -> a
+t
1)
Just k
k -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ k
k forall {k} s (tagged :: * -> k -> *) (b :: k). s -> tagged s b -> s
`asTaggedTypeOf` Tagged k Int
bs
class AsymCipher p v | p -> v, v -> p where
buildKeyPair :: CryptoRandomGen g => g -> BitLength -> Either GenError ((p,v),g)
encryptAsym :: (CryptoRandomGen g) => g -> p -> B.ByteString -> Either GenError (B.ByteString, g)
decryptAsym :: (CryptoRandomGen g) => g -> v -> B.ByteString -> Either GenError (B.ByteString, g)
publicKeyLength :: p -> BitLength
privateKeyLength :: v -> BitLength
buildKeyPairIO :: AsymCipher p v => BitLength -> IO (Either GenError (p,v))
buildKeyPairIO :: forall p v. AsymCipher p v => Int -> IO (Either GenError (p, v))
buildKeyPairIO Int
bl = do
SystemRandom
g <- forall g. CryptoRandomGen g => IO g
newGenIO :: IO SystemRandom
case forall p v g.
(AsymCipher p v, CryptoRandomGen g) =>
g -> Int -> Either GenError ((p, v), g)
buildKeyPair SystemRandom
g Int
bl of
Left GenError
err -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. a -> Either a b
Left GenError
err)
Right ((p, v)
k,SystemRandom
_) -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right (p, v)
k)
buildKeyPairGen :: (CryptoRandomGen g, AsymCipher p v) => BitLength -> g -> Either GenError ((p,v),g)
buildKeyPairGen :: forall g p v.
(CryptoRandomGen g, AsymCipher p v) =>
Int -> g -> Either GenError ((p, v), g)
buildKeyPairGen = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall p v g.
(AsymCipher p v, CryptoRandomGen g) =>
g -> Int -> Either GenError ((p, v), g)
buildKeyPair
class (Serialize k) => StreamCipher k iv | k -> iv where
buildStreamKey :: B.ByteString -> Maybe k
encryptStream :: k -> iv -> B.ByteString -> (B.ByteString, iv)
decryptStream :: k -> iv -> B.ByteString -> (B.ByteString, iv)
streamKeyLength :: Tagged k BitLength
buildStreamKeyIO :: StreamCipher k iv => IO k
buildStreamKeyIO :: forall k iv. StreamCipher k iv => IO k
buildStreamKeyIO = forall (m :: * -> *) k iv.
(Monad m, StreamCipher k iv) =>
(Int -> m ByteString) -> (String -> m k) -> m k
buildStreamKeyM Int -> IO ByteString
getEntropy forall (m :: * -> *) a. MonadFail m => String -> m a
fail
buildStreamKeyGen :: (StreamCipher k iv, CryptoRandomGen g) => g -> Either GenError (k, g)
buildStreamKeyGen :: forall k iv g.
(StreamCipher k iv, CryptoRandomGen g) =>
g -> Either GenError (k, g)
buildStreamKeyGen = forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT (forall (m :: * -> *) k iv.
(Monad m, StreamCipher k iv) =>
(Int -> m ByteString) -> (String -> m k) -> m k
buildStreamKeyM (forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall g.
CryptoRandomGen g =>
Int -> g -> Either GenError (ByteString, g)
genBytes) (forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> Either a b
Left forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> GenError
GenErrorOther))
buildStreamKeyM :: (Monad m, StreamCipher k iv) => (Int -> m B.ByteString) -> (String -> m k) -> m k
buildStreamKeyM :: forall (m :: * -> *) k iv.
(Monad m, StreamCipher k iv) =>
(Int -> m ByteString) -> (String -> m k) -> m k
buildStreamKeyM Int -> m ByteString
getMore String -> m k
err = forall {t} {iv} {iv}.
(Eq t, Num t, StreamCipher k iv, StreamCipher k iv) =>
t -> m k
go (Int
0::Int)
where
go :: t -> m k
go t
1000 = String -> m k
err String
"Tried 1000 times to generate a stream key from the system entropy.\
\ No keys were returned! Perhaps the system entropy is broken\
\ or perhaps the BlockCipher instance being used has a non-flat\
\ keyspace."
go t
i = do
let k :: Tagged k Int
k = forall k iv. StreamCipher k iv => Tagged k Int
streamKeyLength
ByteString
kd <- Int -> m ByteString
getMore ((forall {k} (s :: k) b. Tagged s b -> b
untag Tagged k Int
k forall a. Num a => a -> a -> a
+ Int
7) forall a. Integral a => a -> a -> a
`div` Int
8)
case forall k iv. StreamCipher k iv => ByteString -> Maybe k
buildStreamKey ByteString
kd of
Maybe k
Nothing -> t -> m k
go (t
iforall a. Num a => a -> a -> a
+t
1)
Just k
k' -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ k
k' forall {k} s (tagged :: * -> k -> *) (b :: k). s -> tagged s b -> s
`asTaggedTypeOf` Tagged k Int
k
class (Serialize p, Serialize v) => Signing p v | p -> v, v -> p where
sign :: CryptoRandomGen g => g -> v -> L.ByteString -> Either GenError (B.ByteString, g)
verify :: p -> L.ByteString -> B.ByteString -> Bool
buildSigningPair :: CryptoRandomGen g => g -> BitLength -> Either GenError ((p, v), g)
signingKeyLength :: v -> BitLength
verifyingKeyLength :: p -> BitLength
buildSigningKeyPairIO :: (Signing p v) => BitLength -> IO (Either GenError (p,v))
buildSigningKeyPairIO :: forall p v. Signing p v => Int -> IO (Either GenError (p, v))
buildSigningKeyPairIO Int
bl = do
SystemRandom
g <- forall g. CryptoRandomGen g => IO g
newGenIO :: IO SystemRandom
case forall p v g.
(Signing p v, CryptoRandomGen g) =>
g -> Int -> Either GenError ((p, v), g)
buildSigningPair SystemRandom
g Int
bl of
Left GenError
err -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left GenError
err
Right ((p, v)
k,SystemRandom
_) -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right (p, v)
k
buildSigningKeyPairGen :: (Signing p v, CryptoRandomGen g) => BitLength -> g -> Either GenError ((p, v), g)
buildSigningKeyPairGen :: forall p v g.
(Signing p v, CryptoRandomGen g) =>
Int -> g -> Either GenError ((p, v), g)
buildSigningKeyPairGen = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall p v g.
(Signing p v, CryptoRandomGen g) =>
g -> Int -> Either GenError ((p, v), g)
buildSigningPair
modeEcb' :: BlockCipher k => k -> B.ByteString -> B.ByteString
modeEcb' :: forall k. BlockCipher k => k -> ByteString -> ByteString
modeEcb' k
k ByteString
msg =
let chunks :: [ByteString]
chunks = forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor' k
k ByteString
msg
in [ByteString] -> ByteString
B.concat forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall k. BlockCipher k => k -> ByteString -> ByteString
encryptBlock k
k) [ByteString]
chunks
{-# INLINE modeEcb' #-}
modeUnEcb' :: BlockCipher k => k -> B.ByteString -> B.ByteString
modeUnEcb' :: forall k. BlockCipher k => k -> ByteString -> ByteString
modeUnEcb' k
k ByteString
ct =
let chunks :: [ByteString]
chunks = forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor' k
k ByteString
ct
in [ByteString] -> ByteString
B.concat forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall k. BlockCipher k => k -> ByteString -> ByteString
decryptBlock k
k) [ByteString]
chunks
{-# INLINE modeUnEcb' #-}
modeCbc' :: BlockCipher k => k -> IV k -> B.ByteString -> (B.ByteString, IV k)
modeCbc' :: forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeCbc' k
k (IV ByteString
v) ByteString
plaintext =
let blks :: [ByteString]
blks = forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor' k
k ByteString
plaintext
([ByteString]
cts, ByteString
iv) = [ByteString] -> ByteString -> ([ByteString], ByteString)
go [ByteString]
blks ByteString
v
in ([ByteString] -> ByteString
B.concat [ByteString]
cts, forall k. ByteString -> IV k
IV ByteString
iv)
where
go :: [ByteString] -> ByteString -> ([ByteString], ByteString)
go [] ByteString
iv = ([], ByteString
iv)
go (ByteString
b:[ByteString]
bs) ByteString
iv =
let c :: ByteString
c = forall k. BlockCipher k => k -> ByteString -> ByteString
encryptBlock k
k (ByteString -> ByteString -> ByteString
zwp' ByteString
iv ByteString
b)
([ByteString]
cs, ByteString
ivFinal) = [ByteString] -> ByteString -> ([ByteString], ByteString)
go [ByteString]
bs ByteString
c
in (ByteString
cforall a. a -> [a] -> [a]
:[ByteString]
cs, ByteString
ivFinal)
{-# INLINEABLE modeCbc' #-}
modeUnCbc' :: BlockCipher k => k -> IV k -> B.ByteString -> (B.ByteString, IV k)
modeUnCbc' :: forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCbc' k
k (IV ByteString
v) ByteString
ciphertext =
let blks :: [ByteString]
blks = forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor' k
k ByteString
ciphertext
([ByteString]
pts, ByteString
iv) = [ByteString] -> ByteString -> ([ByteString], ByteString)
go [ByteString]
blks ByteString
v
in ([ByteString] -> ByteString
B.concat [ByteString]
pts, forall k. ByteString -> IV k
IV ByteString
iv)
where
go :: [ByteString] -> ByteString -> ([ByteString], ByteString)
go [] ByteString
iv = ([], ByteString
iv)
go (ByteString
c:[ByteString]
cs) ByteString
iv =
let p :: ByteString
p = ByteString -> ByteString -> ByteString
zwp' (forall k. BlockCipher k => k -> ByteString -> ByteString
decryptBlock k
k ByteString
c) ByteString
iv
([ByteString]
ps, ByteString
ivFinal) = [ByteString] -> ByteString -> ([ByteString], ByteString)
go [ByteString]
cs ByteString
c
in (ByteString
pforall a. a -> [a] -> [a]
:[ByteString]
ps, ByteString
ivFinal)
{-# INLINEABLE modeUnCbc' #-}
modeOfb' :: BlockCipher k => k -> IV k -> B.ByteString -> (B.ByteString, IV k)
modeOfb' :: forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeOfb' = forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnOfb'
{-# INLINEABLE modeOfb' #-}
modeUnOfb' :: BlockCipher k => k -> IV k -> B.ByteString -> (B.ByteString, IV k)
modeUnOfb' :: forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnOfb' k
k (IV ByteString
iv) ByteString
msg =
let ivStr :: [ByteString]
ivStr = Int -> [ByteString] -> [ByteString]
collect (ByteString -> Int
B.length ByteString
msg forall a. Num a => a -> a -> a
+ Int
ivLen) (forall a. Int -> [a] -> [a]
drop Int
1 (forall a. (a -> a) -> a -> [a]
iterate (forall k. BlockCipher k => k -> ByteString -> ByteString
encryptBlock k
k) ByteString
iv))
ivLen :: Int
ivLen = ByteString -> Int
B.length ByteString
iv
mLen :: Int64
mLen = forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
B.length ByteString
msg)
newIV :: IV k
newIV = forall k. ByteString -> IV k
IV forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
B.concat forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int64 -> ByteString -> ByteString
L.take (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ivLen) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int64 -> ByteString -> ByteString
L.drop Int64
mLen forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
L.fromChunks forall a b. (a -> b) -> a -> b
$ [ByteString]
ivStr
in (ByteString -> ByteString -> ByteString
zwp' ([ByteString] -> ByteString
B.concat [ByteString]
ivStr) ByteString
msg, forall {k}. IV k
newIV)
{-# INLINEABLE modeUnOfb' #-}
modeCtr' :: BlockCipher k => (IV k -> IV k) -> k -> IV k -> B.ByteString -> (B.ByteString, IV k)
modeCtr' :: forall k.
BlockCipher k =>
(IV k -> IV k) -> k -> IV k -> ByteString -> (ByteString, IV k)
modeCtr' = forall k.
BlockCipher k =>
(IV k -> IV k) -> k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCtr'
{-# INLINEABLE modeCtr' #-}
modeUnCtr' :: BlockCipher k => (IV k -> IV k) -> k -> IV k -> B.ByteString -> (B.ByteString, IV k)
modeUnCtr' :: forall k.
BlockCipher k =>
(IV k -> IV k) -> k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCtr' IV k -> IV k
f k
k IV k
iv ByteString
msg =
let fa :: (ByteString, IV k) -> Word8 -> ((ByteString, IV k), Word8)
fa (ByteString
st,IV ByteString
iv) Word8
c
| ByteString -> Bool
B.null ByteString
st = (ByteString, IV k) -> Word8 -> ((ByteString, IV k), Word8)
fa (forall k. BlockCipher k => k -> ByteString -> ByteString
encryptBlock k
k ByteString
iv, IV k -> IV k
f (forall k. ByteString -> IV k
IV ByteString
iv)) Word8
c
| Bool
otherwise = let Just (Word8
s,ByteString
nst) = ByteString -> Maybe (Word8, ByteString)
B.uncons ByteString
st in ((ByteString
nst,forall k. ByteString -> IV k
IV ByteString
iv),forall a. Bits a => a -> a -> a
xor Word8
c Word8
s)
((ByteString
_,IV k
newIV),ByteString
res) = forall acc.
(acc -> Word8 -> (acc, Word8))
-> acc -> ByteString -> (acc, ByteString)
B.mapAccumL forall {k}.
(ByteString, IV k) -> Word8 -> ((ByteString, IV k), Word8)
fa (ByteString
B.empty,IV k
iv) ByteString
msg
in (ByteString
res,IV k
newIV)
{-# INLINEABLE modeUnCtr' #-}
modeCfb' :: BlockCipher k => k -> IV k -> B.ByteString -> (B.ByteString, IV k)
modeCfb' :: forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeCfb' k
k (IV ByteString
v) ByteString
msg =
let blks :: [ByteString]
blks = forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor' k
k ByteString
msg
([ByteString]
cs,ByteString
ivF) = ByteString -> [ByteString] -> ([ByteString], ByteString)
go ByteString
v [ByteString]
blks
in ([ByteString] -> ByteString
B.concat [ByteString]
cs, forall k. ByteString -> IV k
IV ByteString
ivF)
where
go :: ByteString -> [ByteString] -> ([ByteString], ByteString)
go ByteString
iv [] = ([],ByteString
iv)
go ByteString
iv (ByteString
b:[ByteString]
bs) =
let c :: ByteString
c = ByteString -> ByteString -> ByteString
zwp' (forall k. BlockCipher k => k -> ByteString -> ByteString
encryptBlock k
k ByteString
iv) ByteString
b
([ByteString]
cs,ByteString
ivFinal) = ByteString -> [ByteString] -> ([ByteString], ByteString)
go ByteString
c [ByteString]
bs
in (ByteString
cforall a. a -> [a] -> [a]
:[ByteString]
cs, ByteString
ivFinal)
{-# INLINEABLE modeCfb' #-}
modeUnCfb' :: BlockCipher k => k -> IV k -> B.ByteString -> (B.ByteString, IV k)
modeUnCfb' :: forall k.
BlockCipher k =>
k -> IV k -> ByteString -> (ByteString, IV k)
modeUnCfb' k
k (IV ByteString
v) ByteString
msg =
let blks :: [ByteString]
blks = forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor' k
k ByteString
msg
([ByteString]
ps, ByteString
ivF) = ByteString -> [ByteString] -> ([ByteString], ByteString)
go ByteString
v [ByteString]
blks
in ([ByteString] -> ByteString
B.concat [ByteString]
ps, forall k. ByteString -> IV k
IV ByteString
ivF)
where
go :: ByteString -> [ByteString] -> ([ByteString], ByteString)
go ByteString
iv [] = ([], ByteString
iv)
go ByteString
iv (ByteString
b:[ByteString]
bs) =
let p :: ByteString
p = ByteString -> ByteString -> ByteString
zwp' (forall k. BlockCipher k => k -> ByteString -> ByteString
encryptBlock k
k ByteString
iv) ByteString
b
([ByteString]
ps, ByteString
ivF) = ByteString -> [ByteString] -> ([ByteString], ByteString)
go ByteString
b [ByteString]
bs
in (ByteString
pforall a. a -> [a] -> [a]
:[ByteString]
ps, ByteString
ivF)
{-# INLINEABLE modeUnCfb' #-}
toChunks :: Int -> B.ByteString -> [B.ByteString]
toChunks :: Int -> ByteString -> [ByteString]
toChunks Int
n ByteString
val = ByteString -> [ByteString]
go ByteString
val
where
go :: ByteString -> [ByteString]
go ByteString
b
| ByteString -> Int
B.length ByteString
b forall a. Eq a => a -> a -> Bool
== Int
0 = []
| Bool
otherwise = let (ByteString
h,ByteString
t) = Int -> ByteString -> (ByteString, ByteString)
B.splitAt Int
n ByteString
b
in ByteString
h forall a. a -> [a] -> [a]
: ByteString -> [ByteString]
go ByteString
t
incIV :: BlockCipher k => IV k -> IV k
incIV :: forall k. BlockCipher k => IV k -> IV k
incIV (IV ByteString
b) = forall k. ByteString -> IV k
IV forall a b. (a -> b) -> a -> b
$ forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall acc.
(acc -> Word8 -> (acc, Word8))
-> acc -> ByteString -> (acc, ByteString)
B.mapAccumR (Word16 -> Word8 -> (Word16, Word8)
incw) Word16
1 ByteString
b
where
incw :: Word16 -> Word8 -> (Word16, Word8)
incw :: Word16 -> Word8 -> (Word16, Word8)
incw Word16
i Word8
w = let nw :: Word16
nw=Word16
iforall a. Num a => a -> a -> a
+(forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w) in (forall a. Bits a => a -> Int -> a
shiftR Word16
nw Int
8, forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
nw)
zeroIV :: (BlockCipher k) => IV k
zeroIV :: forall k. BlockCipher k => IV k
zeroIV = IV k
iv
where bytes :: Int
bytes = forall k. BlockCipher k => IV k -> Int
ivBlockSizeBytes IV k
iv
iv :: IV k
iv = forall k. ByteString -> IV k
IV forall a b. (a -> b) -> a -> b
$ Int -> Word8 -> ByteString
B.replicate Int
bytes Word8
0
zeroIVcwc :: BlockCipher k => IV k
zeroIVcwc :: forall k. BlockCipher k => IV k
zeroIVcwc = IV k
iv
where bytes :: Int
bytes = forall k. BlockCipher k => IV k -> Int
ivBlockSizeBytes IV k
iv forall a. Num a => a -> a -> a
- Int
5
iv :: IV k
iv = forall k. ByteString -> IV k
IV forall a b. (a -> b) -> a -> b
$ Int -> Word8 -> ByteString
B.replicate Int
bytes Word8
0
chunkFor :: (BlockCipher k) => k -> L.ByteString -> [B.ByteString]
chunkFor :: forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor k
k = ByteString -> [ByteString]
go
where
blkSz :: Int
blkSz = (forall k. BlockCipher k => Tagged k Int
blockSize forall a b. Tagged a b -> a -> b
`for` k
k) forall a. Integral a => a -> a -> a
`div` Int
8
blkSzI :: Int64
blkSzI = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
blkSz
go :: ByteString -> [ByteString]
go ByteString
bs | ByteString -> Int64
L.length ByteString
bs forall a. Ord a => a -> a -> Bool
< Int64
blkSzI = []
| Bool
otherwise = let (ByteString
blk,ByteString
rest) = Int64 -> ByteString -> (ByteString, ByteString)
L.splitAt Int64
blkSzI ByteString
bs in [ByteString] -> ByteString
B.concat (ByteString -> [ByteString]
L.toChunks ByteString
blk) forall a. a -> [a] -> [a]
: ByteString -> [ByteString]
go ByteString
rest
{-# INLINE chunkFor #-}
chunkFor' :: (BlockCipher k) => k -> B.ByteString -> [B.ByteString]
chunkFor' :: forall k. BlockCipher k => k -> ByteString -> [ByteString]
chunkFor' k
k = ByteString -> [ByteString]
go
where
blkSz :: Int
blkSz = (forall k. BlockCipher k => Tagged k Int
blockSize forall a b. Tagged a b -> a -> b
`for` k
k) forall a. Integral a => a -> a -> a
`div` Int
8
go :: ByteString -> [ByteString]
go ByteString
bs | ByteString -> Int
B.length ByteString
bs forall a. Ord a => a -> a -> Bool
< Int
blkSz = []
| Bool
otherwise = let (ByteString
blk,ByteString
rest) = Int -> ByteString -> (ByteString, ByteString)
B.splitAt Int
blkSz ByteString
bs in ByteString
blk forall a. a -> [a] -> [a]
: ByteString -> [ByteString]
go ByteString
rest
{-# INLINE chunkFor' #-}
sivMask :: B.ByteString -> B.ByteString
sivMask :: ByteString -> ByteString
sivMask ByteString
b = forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall acc.
(acc -> Word8 -> (acc, Word8))
-> acc -> ByteString -> (acc, ByteString)
B.mapAccumR (Int -> Word8 -> (Int, Word8)
go) Int
0 ByteString
b
where
go :: Int -> Word8 -> (Int,Word8)
go :: Int -> Word8 -> (Int, Word8)
go Int
24 Word8
w = (Int
32,forall a. Bits a => a -> Int -> a
clearBit Word8
w Int
7)
go Int
56 Word8
w = (Int
64,forall a. Bits a => a -> Int -> a
clearBit Word8
w Int
7)
go Int
n Word8
w = (Int
nforall a. Num a => a -> a -> a
+Int
8,Word8
w)
ivBlockSizeBytes :: BlockCipher k => IV k -> Int
ivBlockSizeBytes :: forall k. BlockCipher k => IV k -> Int
ivBlockSizeBytes IV k
iv =
let p :: Proxy k
p = forall k. Proxy (IV k) -> Proxy k
deIVProxy (forall a. a -> Proxy a
proxyOf IV k
iv)
in forall {k} (s :: k) a (proxy :: k -> *). Tagged s a -> proxy s -> a
proxy forall k. BlockCipher k => Tagged k Int
blockSize Proxy k
p forall a. Integral a => a -> a -> a
`div` Int
8
where
proxyOf :: a -> Proxy a
proxyOf :: forall a. a -> Proxy a
proxyOf = forall a b. a -> b -> a
const forall {k} (t :: k). Proxy t
Proxy
{-# INLINEABLE ivBlockSizeBytes #-}
instance (BlockCipher k) => Serialize (IV k) where
get :: Get (IV k)
get = do
let p :: Proxy t
p = forall {k} (t :: k). Proxy t
Proxy
doGet :: BlockCipher k => Proxy k -> Get (IV k)
doGet :: forall k. BlockCipher k => Proxy k -> Get (IV k)
doGet Proxy k
pr = forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM forall k. ByteString -> IV k
IV (Int -> Get ByteString
SG.getByteString (forall {k} (s :: k) a (proxy :: k -> *). Tagged s a -> proxy s -> a
proxy forall k. BlockCipher k => Tagged k Int
blockSizeBytes Proxy k
pr))
IV k
iv <- forall k. BlockCipher k => Proxy k -> Get (IV k)
doGet forall {t}. Proxy t
p
forall (m :: * -> *) a. Monad m => a -> m a
return (IV k
iv forall a (proxy :: * -> *). a -> proxy a -> a
`asProxyTypeOf` forall k. Proxy k -> Proxy (IV k)
ivProxy forall {t}. Proxy t
p)
put :: Putter (IV k)
put (IV ByteString
iv) = Putter ByteString
SP.putByteString ByteString
iv