-- | -- Module : Crypto.Random -- License : BSD-style -- Maintainer : Vincent Hanquez <vincent@snarc.org> -- Stability : experimental -- Portability : Good -- -- Provide a safe abstraction for cryptographic pseudo -- random generator. -- {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE DeriveDataTypeable #-} module Crypto.Random ( -- * Entropy EntropyPool , createEntropyPool , grabEntropy , grabEntropyIO -- * Random generation , CPRG(..) , withRandomBytes -- * System generator , SystemRNG -- * Testing and mocking , createTestEntropyPool ) where import Crypto.Random.Entropy import Crypto.Random.Generator import Data.ByteString (ByteString) import Data.Typeable (Typeable) import qualified Data.ByteString.Internal as B (unsafeCreate) -- | System entropy generator. -- -- This generator doesn't use the entropy reseed level, as the only bytes -- generated are comping from the entropy pool already. -- -- This generator doesn't create reproducible output, and might be difficult to -- use for testing and debugging purpose, but otherwise for real world use case -- should be fine. data SystemRNG = SystemRNG EntropyPool deriving Typeable instance CPRG SystemRNG where cprgCreate entPool = SystemRNG entPool cprgSetReseedThreshold _ r = r cprgFork r@(SystemRNG entPool) = (r, cprgCreate entPool) cprgGenerate n g@(SystemRNG entPool) = (B.unsafeCreate n (grabEntropyPtr n entPool), g) -- we don't need to do anything different when generating withEntropy, as the generated -- bytes are already stricly entropy bytes. cprgGenerateWithEntropy n g = cprgGenerate n g -- | generate @len random bytes and mapped the bytes to the function @f. -- -- This is equivalent to use Control.Arrow 'first' with 'cprgGenerate' withRandomBytes :: CPRG g => g -> Int -> (ByteString -> a) -> (a, g) withRandomBytes rng len f = (f bs, rng') where (bs, rng') = cprgGenerate len rng