crypto-random-api 0.1.0 → 0.2.0
raw patch · 2 files changed
+81/−19 lines, 2 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Crypto.Random.API: NeverReseed :: ReseedPolicy
+ Crypto.Random.API: ReseedInBytes :: Word64 -> ReseedPolicy
+ Crypto.Random.API: data ReseedPolicy
+ Crypto.Random.API: data SystemRandom
+ Crypto.Random.API: genRandomBytes' :: CPRG g => Int -> g -> ([ByteString], g)
+ Crypto.Random.API: getSystemRandomGen :: IO SystemRandom
+ Crypto.Random.API: instance CPRG SystemRandom
+ Crypto.Random.API: instance Eq ReseedPolicy
+ Crypto.Random.API: instance Show ReseedPolicy
- Crypto.Random.API: cprgGenBytes :: CPRG g => g -> Int -> (ByteString, g)
+ Crypto.Random.API: cprgGenBytes :: CPRG g => Int -> g -> (ByteString, g)
- Crypto.Random.API: cprgNeedReseed :: CPRG g => g -> Int
+ Crypto.Random.API: cprgNeedReseed :: CPRG g => g -> ReseedPolicy
- Crypto.Random.API: cprgSupplyEntropy :: CPRG g => g -> ByteString -> g
+ Crypto.Random.API: cprgSupplyEntropy :: CPRG g => ByteString -> g -> g
- Crypto.Random.API: genRandomBytes :: CPRG g => g -> Int -> (ByteString, g)
+ Crypto.Random.API: genRandomBytes :: CPRG g => Int -> g -> (ByteString, g)
Files
- Crypto/Random/API.hs +80/−18
- crypto-random-api.cabal +1/−1
Crypto/Random/API.hs view
@@ -7,15 +7,34 @@ module Crypto.Random.API ( CPRG(..)+ , ReseedPolicy(..) , genRandomBytes+ , genRandomBytes' , withRandomBytes , getSystemEntropy+ -- * System Random generator+ , SystemRandom+ , getSystemRandomGen ) where +import Control.Applicative import qualified Data.ByteString as B import Data.ByteString (ByteString)-import System.Entropy (getEntropy)+import qualified System.Entropy as SE+import System.IO.Unsafe (unsafeInterleaveIO)+import Data.Word +-- | This is the reseed policy requested by the CPRG+data ReseedPolicy =+ NeverReseed -- ^ there is no need to reseed as either+ -- the RG doesn't supports it, it's done automatically+ -- or pratically the reseeding period exceed a Word64 type.+ | ReseedInBytes Word64 -- ^ the RG need to be reseed in the number+ -- of bytes joined to the type. it should be done before+ -- the number reached 0, otherwise an user of the RG+ -- might request too many bytes and get repeated random bytes.+ deriving (Show,Eq)+ -- | A class of Cryptographic Secure Random generator. -- -- The main difference with the generic haskell RNG is that@@ -25,7 +44,7 @@ -- 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+-- is expected 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,@@ -35,39 +54,82 @@ -- 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+ cprgNeedReseed :: g -> ReseedPolicy -- | 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+ cprgSupplyEntropy :: ByteString -> g -> 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)+ -- instead of this method directly. the CPRG need to be able+ -- to supply at minimum 2^20 bytes at a time.+ cprgGenBytes :: Int -> g -> (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+--+-- If the number of bytes requested is really high,+-- it's preferable to use 'genRandomBytes' for better memory efficiency.+genRandomBytes :: CPRG g => Int -- ^ number of bytes to return+ -> g -- ^ CPRG to use -> (ByteString, g)-genRandomBytes rng len+genRandomBytes len rng = (\(lbs,g) -> (B.concat lbs, g)) $ genRandomBytes' len rng++-- | Generate bytes using the cprg in parameter.+--+-- This is not tail recursive and an excessive len (>= 2^29) parameter would+-- result in stack overflow.+genRandomBytes' :: CPRG g => Int -- ^ number of bytes to return+ -> g -- ^ CPRG to use+ -> ([ByteString], g)+genRandomBytes' len rng | 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+ | otherwise = loop rng len+ where loop g len+ | len == 0 = ([], g)+ | otherwise = let itBytes = min (2^20) len+ (bs, g') = cprgGenBytes itBytes g+ (l, g'') = genRandomBytes' (len-itBytes) g'+ in (bs:l, g'') --- | this is equivalent to using Control.Arrow 'first' with genBytes.+-- | this is equivalent to using Control.Arrow 'first' with 'genRandomBytes'. -- -- 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+ where (bs, rng') = genRandomBytes len rng -- | Return system entropy using the entropy package 'getEntropy' getSystemEntropy :: Int -> IO ByteString-getSystemEntropy = getEntropy+getSystemEntropy = SE.getEntropy++-- | This is a simple generator that pull bytes from the system entropy+-- directly. Its randomness and security properties are absolutely+-- depends on the underlaying system implementation.+data SystemRandom = SystemRandom [B.ByteString]++-- | Get a random number generator based on the standard system entropy source+getSystemRandomGen :: IO SystemRandom+getSystemRandomGen = do+ ch <- SE.openHandle+ let getBS = unsafeInterleaveIO $ do+ bs <- SE.hGetEntropy ch 8192+ more <- getBS+ return (bs:more)+ SystemRandom <$> getBS++instance CPRG SystemRandom where+ cprgNeedReseed _ = NeverReseed+ cprgSupplyEntropy _ g = g+ cprgGenBytes n (SystemRandom l) = (B.concat l1, SystemRandom l2)+ where (l1, l2) = lbsSplitAt n l+ lbsSplitAt rBytes (x:xs)+ | xLen >= rBytes =+ let (b1,b2) = B.splitAt rBytes x+ in ([b1], b2:xs)+ | otherwise =+ let (l1,l2) = lbsSplitAt (rBytes-xLen) xs+ in (x:l1,l2)+ where xLen = B.length x
crypto-random-api.cabal view
@@ -1,5 +1,5 @@ Name: crypto-random-api-Version: 0.1.0+Version: 0.2.0 Description: Simple random generators API for cryptography related code License: BSD3 License-file: LICENSE