-- | -- Module : Crypto.Random.API -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good module Crypto.Random.API ( CPRG(..) , genRandomBytes , withRandomBytes , getSystemEntropy ) where import qualified Data.ByteString as B import Data.ByteString (ByteString) import System.Entropy (getEntropy) -- | A class of Cryptographic Secure Random generator. -- -- The main difference with the generic haskell RNG is that -- it return bytes instead of integer. -- -- It is quite similar to the CryptoRandomGen class in crypto-api -- except that error are not returned to the user. Instead -- the user is suppose to handle reseeding by using the NeedReseed -- and SupplyEntropy methods. For other type of errors, the user -- is expect to generate bytes with the parameters bounds explicity -- defined here. -- -- The CPRG need to be able to generate up to 2^20 bytes in one call, -- class CPRG g where -- | Provide a way to query the CPRG to calculate when new entropy -- is required to be supplied so the CPRG doesn't repeat output, and -- break assumptions. This returns the number of bytes before -- which supply entropy should have been called. cprgNeedReseed :: g -> Int -- | Supply entropy to the CPRG, that can be used now or later -- to reseed the CPRG. This should be used in conjunction to -- NeedReseed to know when to supply entropy. cprgSupplyEntropy :: g -> ByteString -> g -- | Generate bytes using the CPRG and the number specified. -- -- For user of the API, it's recommended to use genRandomBytes -- instead of this method directly. cprgGenBytes :: g -> Int -> (ByteString, g) -- | Generate bytes using the cprg in parameter. -- -- arbitrary limit the number of bytes that can be generated in -- one go to 10mb. genRandomBytes :: CPRG g => g -- ^ CPRG to use -> Int -- ^ number of bytes to return -> (ByteString, g) genRandomBytes rng len | len < 0 = error "genBytes: cannot request negative amount of bytes." | len > 2^20 = error "genBytes: cannot request more than 1mb of bytes in one go." | len == 0 = (B.empty, rng) | otherwise = cprgGenBytes rng len -- | this is equivalent to using Control.Arrow 'first' with genBytes. -- -- namely it generate @len bytes and map the bytes to the function @f withRandomBytes :: CPRG g => g -> Int -> (ByteString -> a) -> (a, g) withRandomBytes rng len f = (f bs, rng') where (bs, rng') = genRandomBytes rng len -- | Return system entropy using the entropy package 'getEntropy' getSystemEntropy :: Int -> IO ByteString getSystemEntropy = getEntropy