packages feed

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 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