{-# LANGUAGE FlexibleInstances, TypeSynonymInstances, DeriveDataTypeable, CPP,
BangPatterns #-}
module Crypto.Random
(
CryptoRandomGen(..)
, GenError (..)
, ReseedInfo (..)
, splitGen
, throwLeft
, SystemRandom
) where
import Control.Monad (liftM)
import Control.Exception
import Crypto.Types
import Crypto.Util
import Data.Bits (xor, setBit, shiftR, shiftL, (.&.))
import Data.Data
import Data.List (foldl')
import Data.Tagged
import Data.Typeable
import Data.Word
import System.Entropy
import System.IO.Unsafe(unsafeInterleaveIO)
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import qualified Foreign.ForeignPtr as FP
#if MIN_VERSION_tagged(0,2,0)
import Data.Proxy
#endif
data GenError =
GenErrorOther String
| RequestedTooManyBytes
| RangeInvalid
| NeedReseed
| NotEnoughEntropy
| NeedsInfiniteSeed
deriving (GenError -> GenError -> Bool
(GenError -> GenError -> Bool)
-> (GenError -> GenError -> Bool) -> Eq GenError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: GenError -> GenError -> Bool
== :: GenError -> GenError -> Bool
$c/= :: GenError -> GenError -> Bool
/= :: GenError -> GenError -> Bool
Eq, Eq GenError
Eq GenError =>
(GenError -> GenError -> Ordering)
-> (GenError -> GenError -> Bool)
-> (GenError -> GenError -> Bool)
-> (GenError -> GenError -> Bool)
-> (GenError -> GenError -> Bool)
-> (GenError -> GenError -> GenError)
-> (GenError -> GenError -> GenError)
-> Ord GenError
GenError -> GenError -> Bool
GenError -> GenError -> Ordering
GenError -> GenError -> GenError
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: GenError -> GenError -> Ordering
compare :: GenError -> GenError -> Ordering
$c< :: GenError -> GenError -> Bool
< :: GenError -> GenError -> Bool
$c<= :: GenError -> GenError -> Bool
<= :: GenError -> GenError -> Bool
$c> :: GenError -> GenError -> Bool
> :: GenError -> GenError -> Bool
$c>= :: GenError -> GenError -> Bool
>= :: GenError -> GenError -> Bool
$cmax :: GenError -> GenError -> GenError
max :: GenError -> GenError -> GenError
$cmin :: GenError -> GenError -> GenError
min :: GenError -> GenError -> GenError
Ord, Int -> GenError -> ShowS
[GenError] -> ShowS
GenError -> String
(Int -> GenError -> ShowS)
-> (GenError -> String) -> ([GenError] -> ShowS) -> Show GenError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> GenError -> ShowS
showsPrec :: Int -> GenError -> ShowS
$cshow :: GenError -> String
show :: GenError -> String
$cshowList :: [GenError] -> ShowS
showList :: [GenError] -> ShowS
Show, ReadPrec [GenError]
ReadPrec GenError
Int -> ReadS GenError
ReadS [GenError]
(Int -> ReadS GenError)
-> ReadS [GenError]
-> ReadPrec GenError
-> ReadPrec [GenError]
-> Read GenError
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS GenError
readsPrec :: Int -> ReadS GenError
$creadList :: ReadS [GenError]
readList :: ReadS [GenError]
$creadPrec :: ReadPrec GenError
readPrec :: ReadPrec GenError
$creadListPrec :: ReadPrec [GenError]
readListPrec :: ReadPrec [GenError]
Read, Typeable GenError
Typeable GenError =>
(forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> GenError -> c GenError)
-> (forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c GenError)
-> (GenError -> Constr)
-> (GenError -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c GenError))
-> (forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c GenError))
-> ((forall b. Data b => b -> b) -> GenError -> GenError)
-> (forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> GenError -> r)
-> (forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> GenError -> r)
-> (forall u. (forall d. Data d => d -> u) -> GenError -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> GenError -> u)
-> (forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> GenError -> m GenError)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> GenError -> m GenError)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> GenError -> m GenError)
-> Data GenError
GenError -> Constr
GenError -> DataType
(forall b. Data b => b -> b) -> GenError -> GenError
forall a.
Typeable a =>
(forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> GenError -> u
forall u. (forall d. Data d => d -> u) -> GenError -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> GenError -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> GenError -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> GenError -> m GenError
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> GenError -> m GenError
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c GenError
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> GenError -> c GenError
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c GenError)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c GenError)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> GenError -> c GenError
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> GenError -> c GenError
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c GenError
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c GenError
$ctoConstr :: GenError -> Constr
toConstr :: GenError -> Constr
$cdataTypeOf :: GenError -> DataType
dataTypeOf :: GenError -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c GenError)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c GenError)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c GenError)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c GenError)
$cgmapT :: (forall b. Data b => b -> b) -> GenError -> GenError
gmapT :: (forall b. Data b => b -> b) -> GenError -> GenError
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> GenError -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> GenError -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> GenError -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> GenError -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> GenError -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> GenError -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> GenError -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> GenError -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> GenError -> m GenError
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> GenError -> m GenError
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> GenError -> m GenError
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> GenError -> m GenError
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> GenError -> m GenError
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> GenError -> m GenError
Data, Typeable)
data ReseedInfo
= InXBytes {-# UNPACK #-} !Word64
| InXCalls {-# UNPACK #-} !Word64
| NotSoon
| Never
deriving (ReseedInfo -> ReseedInfo -> Bool
(ReseedInfo -> ReseedInfo -> Bool)
-> (ReseedInfo -> ReseedInfo -> Bool) -> Eq ReseedInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ReseedInfo -> ReseedInfo -> Bool
== :: ReseedInfo -> ReseedInfo -> Bool
$c/= :: ReseedInfo -> ReseedInfo -> Bool
/= :: ReseedInfo -> ReseedInfo -> Bool
Eq, Eq ReseedInfo
Eq ReseedInfo =>
(ReseedInfo -> ReseedInfo -> Ordering)
-> (ReseedInfo -> ReseedInfo -> Bool)
-> (ReseedInfo -> ReseedInfo -> Bool)
-> (ReseedInfo -> ReseedInfo -> Bool)
-> (ReseedInfo -> ReseedInfo -> Bool)
-> (ReseedInfo -> ReseedInfo -> ReseedInfo)
-> (ReseedInfo -> ReseedInfo -> ReseedInfo)
-> Ord ReseedInfo
ReseedInfo -> ReseedInfo -> Bool
ReseedInfo -> ReseedInfo -> Ordering
ReseedInfo -> ReseedInfo -> ReseedInfo
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ReseedInfo -> ReseedInfo -> Ordering
compare :: ReseedInfo -> ReseedInfo -> Ordering
$c< :: ReseedInfo -> ReseedInfo -> Bool
< :: ReseedInfo -> ReseedInfo -> Bool
$c<= :: ReseedInfo -> ReseedInfo -> Bool
<= :: ReseedInfo -> ReseedInfo -> Bool
$c> :: ReseedInfo -> ReseedInfo -> Bool
> :: ReseedInfo -> ReseedInfo -> Bool
$c>= :: ReseedInfo -> ReseedInfo -> Bool
>= :: ReseedInfo -> ReseedInfo -> Bool
$cmax :: ReseedInfo -> ReseedInfo -> ReseedInfo
max :: ReseedInfo -> ReseedInfo -> ReseedInfo
$cmin :: ReseedInfo -> ReseedInfo -> ReseedInfo
min :: ReseedInfo -> ReseedInfo -> ReseedInfo
Ord, Int -> ReseedInfo -> ShowS
[ReseedInfo] -> ShowS
ReseedInfo -> String
(Int -> ReseedInfo -> ShowS)
-> (ReseedInfo -> String)
-> ([ReseedInfo] -> ShowS)
-> Show ReseedInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ReseedInfo -> ShowS
showsPrec :: Int -> ReseedInfo -> ShowS
$cshow :: ReseedInfo -> String
show :: ReseedInfo -> String
$cshowList :: [ReseedInfo] -> ShowS
showList :: [ReseedInfo] -> ShowS
Show, ReadPrec [ReseedInfo]
ReadPrec ReseedInfo
Int -> ReadS ReseedInfo
ReadS [ReseedInfo]
(Int -> ReadS ReseedInfo)
-> ReadS [ReseedInfo]
-> ReadPrec ReseedInfo
-> ReadPrec [ReseedInfo]
-> Read ReseedInfo
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS ReseedInfo
readsPrec :: Int -> ReadS ReseedInfo
$creadList :: ReadS [ReseedInfo]
readList :: ReadS [ReseedInfo]
$creadPrec :: ReadPrec ReseedInfo
readPrec :: ReadPrec ReseedInfo
$creadListPrec :: ReadPrec [ReseedInfo]
readListPrec :: ReadPrec [ReseedInfo]
Read, Typeable ReseedInfo
Typeable ReseedInfo =>
(forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ReseedInfo -> c ReseedInfo)
-> (forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ReseedInfo)
-> (ReseedInfo -> Constr)
-> (ReseedInfo -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ReseedInfo))
-> (forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c ReseedInfo))
-> ((forall b. Data b => b -> b) -> ReseedInfo -> ReseedInfo)
-> (forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ReseedInfo -> r)
-> (forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ReseedInfo -> r)
-> (forall u. (forall d. Data d => d -> u) -> ReseedInfo -> [u])
-> (forall u.
Int -> (forall d. Data d => d -> u) -> ReseedInfo -> u)
-> (forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ReseedInfo -> m ReseedInfo)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ReseedInfo -> m ReseedInfo)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ReseedInfo -> m ReseedInfo)
-> Data ReseedInfo
ReseedInfo -> Constr
ReseedInfo -> DataType
(forall b. Data b => b -> b) -> ReseedInfo -> ReseedInfo
forall a.
Typeable a =>
(forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> ReseedInfo -> u
forall u. (forall d. Data d => d -> u) -> ReseedInfo -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ReseedInfo -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ReseedInfo -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ReseedInfo -> m ReseedInfo
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ReseedInfo -> m ReseedInfo
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ReseedInfo
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ReseedInfo -> c ReseedInfo
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ReseedInfo)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ReseedInfo)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ReseedInfo -> c ReseedInfo
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ReseedInfo -> c ReseedInfo
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ReseedInfo
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ReseedInfo
$ctoConstr :: ReseedInfo -> Constr
toConstr :: ReseedInfo -> Constr
$cdataTypeOf :: ReseedInfo -> DataType
dataTypeOf :: ReseedInfo -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ReseedInfo)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ReseedInfo)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ReseedInfo)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ReseedInfo)
$cgmapT :: (forall b. Data b => b -> b) -> ReseedInfo -> ReseedInfo
gmapT :: (forall b. Data b => b -> b) -> ReseedInfo -> ReseedInfo
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ReseedInfo -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ReseedInfo -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ReseedInfo -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ReseedInfo -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> ReseedInfo -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> ReseedInfo -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> ReseedInfo -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> ReseedInfo -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ReseedInfo -> m ReseedInfo
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ReseedInfo -> m ReseedInfo
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ReseedInfo -> m ReseedInfo
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ReseedInfo -> m ReseedInfo
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ReseedInfo -> m ReseedInfo
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ReseedInfo -> m ReseedInfo
Data, Typeable)
instance Exception GenError
class CryptoRandomGen g where
newGen :: B.ByteString -> Either GenError g
genSeedLength :: Tagged g ByteLength
genBytes :: ByteLength -> g -> Either GenError (B.ByteString, g)
reseedInfo :: g -> ReseedInfo
reseedPeriod :: g -> ReseedInfo
genBytesWithEntropy :: ByteLength -> B.ByteString -> g -> Either GenError (B.ByteString, g)
genBytesWithEntropy Int
len ByteString
entropy g
g =
let res :: Either GenError (ByteString, g)
res = Int -> g -> Either GenError (ByteString, g)
forall g.
CryptoRandomGen g =>
Int -> g -> Either GenError (ByteString, g)
genBytes Int
len g
g
in case Either GenError (ByteString, g)
res of
Left GenError
err -> GenError -> Either GenError (ByteString, g)
forall a b. a -> Either a b
Left GenError
err
Right (ByteString
bs,g
g') ->
let entropy' :: ByteString
entropy' = ByteString -> ByteString -> ByteString
B.append ByteString
entropy (Int -> Word8 -> ByteString
B.replicate (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- ByteString -> Int
B.length ByteString
entropy) Word8
0)
in (ByteString, g) -> Either GenError (ByteString, g)
forall a b. b -> Either a b
Right (ByteString -> ByteString -> ByteString
zwp' ByteString
entropy' ByteString
bs, g
g')
reseed :: B.ByteString -> g -> Either GenError g
newGenIO :: IO g
newGenIO = Integer -> IO g
forall {t} {b}. (Eq t, Num t, CryptoRandomGen b) => t -> IO b
go Integer
0
where
go :: t -> IO b
go t
1000 = GenError -> IO b
forall a e. Exception e => e -> a
throw (GenError -> IO b) -> GenError -> IO b
forall a b. (a -> b) -> a -> b
$ String -> GenError
GenErrorOther (String -> GenError) -> String -> GenError
forall a b. (a -> b) -> a -> b
$
String
"The generator instance requested by" String -> ShowS
forall a. [a] -> [a] -> [a]
++
String
"newGenIO never instantiates (1000 tries). " String -> ShowS
forall a. [a] -> [a] -> [a]
++
String
"It must be broken."
go t
i = do
let p :: Proxy t
p = Proxy t
forall {k} (t :: k). Proxy t
Proxy
getTypedGen :: (CryptoRandomGen g) => Proxy g -> IO (Either GenError g)
getTypedGen :: forall g. CryptoRandomGen g => Proxy g -> IO (Either GenError g)
getTypedGen Proxy g
pr = (ByteString -> Either GenError g)
-> IO ByteString -> IO (Either GenError g)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ByteString -> Either GenError g
forall g. CryptoRandomGen g => ByteString -> Either GenError g
newGen (Int -> IO ByteString
getEntropy (Int -> IO ByteString) -> Int -> IO ByteString
forall a b. (a -> b) -> a -> b
$ Tagged g Int -> Proxy g -> Int
forall {k} (s :: k) a (proxy :: k -> *). Tagged s a -> proxy s -> a
proxy Tagged g Int
forall g. CryptoRandomGen g => Tagged g Int
genSeedLength Proxy g
pr)
Either GenError b
res <- Proxy b -> IO (Either GenError b)
forall g. CryptoRandomGen g => Proxy g -> IO (Either GenError g)
getTypedGen Proxy b
forall {t}. Proxy t
p
case Either GenError b
res of
Left GenError
_ -> t -> IO b
go (t
it -> t -> t
forall a. Num a => a -> a -> a
+t
1)
Right b
g -> b -> IO b
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (b
g b -> Proxy b -> b
forall a (proxy :: * -> *). a -> proxy a -> a
`asProxyTypeOf` Proxy b
forall {t}. Proxy t
p)
getSystemGen :: IO SystemRandom
getSystemGen :: IO SystemRandom
getSystemGen = do
CryptHandle
ch <- IO CryptHandle
openHandle
let getBS :: IO [ByteString]
getBS = IO [ByteString] -> IO [ByteString]
forall a. IO a -> IO a
unsafeInterleaveIO (IO [ByteString] -> IO [ByteString])
-> IO [ByteString] -> IO [ByteString]
forall a b. (a -> b) -> a -> b
$ do
ByteString
bs <- CryptHandle -> Int -> IO ByteString
hGetEntropy CryptHandle
ch ((Int
2Int -> Integer -> Int
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
15) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
16)
[ByteString]
more <- IO [ByteString]
getBS
[ByteString] -> IO [ByteString]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString
bsByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
more)
([ByteString] -> SystemRandom)
-> IO [ByteString] -> IO SystemRandom
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (ByteString -> SystemRandom
SysRandom (ByteString -> SystemRandom)
-> ([ByteString] -> ByteString) -> [ByteString] -> SystemRandom
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
L.fromChunks) IO [ByteString]
getBS
data SystemRandom = SysRandom L.ByteString
instance CryptoRandomGen SystemRandom where
newGen :: ByteString -> Either GenError SystemRandom
newGen ByteString
_ = GenError -> Either GenError SystemRandom
forall a b. a -> Either a b
Left GenError
NeedsInfiniteSeed
genSeedLength :: Tagged SystemRandom Int
genSeedLength = Int -> Tagged SystemRandom Int
forall {k} (s :: k) b. b -> Tagged s b
Tagged Int
forall a. Bounded a => a
maxBound
genBytes :: Int -> SystemRandom -> Either GenError (ByteString, SystemRandom)
genBytes Int
req (SysRandom ByteString
bs) =
let reqI :: Int64
reqI = Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
req
rnd :: ByteString
rnd = Int64 -> ByteString -> ByteString
L.take Int64
reqI ByteString
bs
rest :: ByteString
rest = Int64 -> ByteString -> ByteString
L.drop Int64
reqI ByteString
bs
in if ByteString -> Int64
L.length ByteString
rnd Int64 -> Int64 -> Bool
forall a. Eq a => a -> a -> Bool
== Int64
reqI
then (ByteString, SystemRandom)
-> Either GenError (ByteString, SystemRandom)
forall a b. b -> Either a b
Right ([ByteString] -> ByteString
B.concat ([ByteString] -> ByteString) -> [ByteString] -> ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> [ByteString]
L.toChunks ByteString
rnd, ByteString -> SystemRandom
SysRandom ByteString
rest)
else GenError -> Either GenError (ByteString, SystemRandom)
forall a b. a -> Either a b
Left GenError
RequestedTooManyBytes
reseed :: ByteString -> SystemRandom -> Either GenError SystemRandom
reseed ByteString
_ SystemRandom
_ = GenError -> Either GenError SystemRandom
forall a b. a -> Either a b
Left GenError
NeedsInfiniteSeed
newGenIO :: IO SystemRandom
newGenIO = IO SystemRandom
getSystemGen
reseedInfo :: SystemRandom -> ReseedInfo
reseedInfo SystemRandom
_ = ReseedInfo
Never
reseedPeriod :: SystemRandom -> ReseedInfo
reseedPeriod SystemRandom
_ = ReseedInfo
Never
splitGen :: CryptoRandomGen g => g -> Either GenError (g,g)
splitGen :: forall g. CryptoRandomGen g => g -> Either GenError (g, g)
splitGen g
g =
let e :: Either GenError (ByteString, g)
e = Int -> g -> Either GenError (ByteString, g)
forall g.
CryptoRandomGen g =>
Int -> g -> Either GenError (ByteString, g)
genBytes (Tagged g Int
forall g. CryptoRandomGen g => Tagged g Int
genSeedLength Tagged g Int -> g -> Int
forall a b. Tagged a b -> a -> b
`for` g
g) g
g
in case Either GenError (ByteString, g)
e of
Left GenError
e -> GenError -> Either GenError (g, g)
forall a b. a -> Either a b
Left GenError
e
Right (ByteString
ent,g
g') ->
case ByteString -> Either GenError g
forall g. CryptoRandomGen g => ByteString -> Either GenError g
newGen ByteString
ent of
Right g
new -> (g, g) -> Either GenError (g, g)
forall a b. b -> Either a b
Right (g
g',g
new)
Left GenError
e -> GenError -> Either GenError (g, g)
forall a b. a -> Either a b
Left GenError
e