DRBG 0.1.2 → 0.1.3
raw patch · 3 files changed
+84/−22 lines, 3 filesdep ~taggedPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: tagged
API changes (from Hackage documentation)
+ Crypto.Random.DRBG: newGenAutoReseed :: (CryptoRandomGen a, CryptoRandomGen b) => ByteString -> Int -> Either GenError (GenAutoReseed a b)
+ Crypto.Random.DRBG: newGenAutoReseedIO :: (CryptoRandomGen a, CryptoRandomGen b) => Int -> IO (Either GenError (GenAutoReseed a b))
Files
- CHANGELOG +4/−0
- Crypto/Random/DRBG.hs +78/−20
- DRBG.cabal +2/−2
CHANGELOG view
@@ -1,3 +1,7 @@+0.1.3+* Updated to work with tagged == 0.2.+* Exported newGenAutoReseed{,IO} for those really really long running CRG's.+ 0.1.2 * Verify the seed length is sufficient when instantiating or reseeding HmacDRBG and HashDRBG * Move GenSystemRandom out of DRBG (into crypto-api >= 0.3)
Crypto/Random/DRBG.hs view
@@ -36,7 +36,7 @@ ( HmacDRBG, HashDRBG , HmacDRBGWith, HashDRBGWith , GenXor- , GenAutoReseed+ , GenAutoReseed, newGenAutoReseed, newGenAutoReseedIO , GenBuffered , module Crypto.Random ) where@@ -54,6 +54,7 @@ import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L import Data.Tagged+import Data.Proxy import Data.Bits (xor) import Control.Parallel import Control.Monad (liftM)@@ -89,6 +90,21 @@ -- |An Alias for a Hash DRBG generator using SHA512. type HashDRBG = H.State SHA512 +-- |@newGenAutoReseed bs i@ creates a new 'GenAutoReseed' with a custom interval+-- of @i@ bytes using the provided entropy in @bs@.+--+-- This is for extremely long running uses of 'CryptoRandomGen' instances+-- that can't explicitly reseed as often as a single underlying generator+-- would need (usually every 2^48 bytes).+--+-- For example:+--+-- @+-- newGenAutoReseedIO (2^48) :: IO (Either GenError (GenAutoReseed HashDRBG HashDRBG))+-- @+-- +-- Will last for @2^48 * 2^48@ bytes of randomly generated data. That's+-- 2^56 terabytes of random values. newGenAutoReseed :: (CryptoRandomGen a, CryptoRandomGen b) => B.ByteString -> Int -> Either GenError (GenAutoReseed a b) newGenAutoReseed bs rsInterval= let (b1,b2) = B.splitAt (genSeedLength `for` fromRight g1) bs@@ -100,6 +116,27 @@ (Left e, _) -> Left e (_, Left e) -> Left e +-- |@newGenAutoReseedIO i@ creates a new 'GenAutoReseed' with a custom+-- interval of @i@ bytes, using the system random number generator as a seed.+--+-- See 'newGenAutoReseed'.+newGenAutoReseedIO :: (CryptoRandomGen a, CryptoRandomGen b) =>+ Int -> IO (Either GenError (GenAutoReseed a b))+newGenAutoReseedIO i = do+ let p = Proxy+ getG :: (CryptoRandomGen a, CryptoRandomGen b) => + Proxy (GenAutoReseed a b) -> IO (Either GenError (GenAutoReseed a b))+ getG p = liftM (\bs -> newGenAutoReseed bs i `asProxyTypeOf` rightProxy p)+ (getEntropy (seed p))+ g <- getG p+ return (g `asProxyTypeOf` p)++seed :: CryptoRandomGen g => Proxy g -> Int+seed x = proxy genSeedLength x++rightProxy :: Proxy p -> Proxy (Either x p)+rightProxy = reproxy+ instance CryptoRandomGen HmacDRBG where newGen bs = let res = M.instantiate bs B.empty B.empty@@ -163,9 +200,15 @@ -- Note a request for > 32KB of data will be filled in one request to generator @a@ before -- @a@ is reseeded by @b@. ----- @genBytesWithEntropy@ will push the entropy into generator @a@, leaving generator--- @b@ unchanged unless the count hits 32KB, in which case it is reseeds @a@ --- (for a second time) using @b@ as in normal operation via @genBytes@.+-- @genBytesWithEntropy@ is lifted into the same call for generator @a@, but+-- it will still reseed from generator @b@ if the limit is hit.+--+-- Reseed interval: If generator @a@ needs a @genSeedLength a = a'@ and generator B+-- needs reseeded every @2^b@ bytes then a @GenAutoReseed a b@ will need reseeded every+-- @2^15 * (2^b / a')@ bytes. For the common values of @a' = 128@ and @2^b = 2^48@ this+-- means reseeding every 2^56 bytes (an extra factor of 2^8 for every nesting of+-- GenAutoReseed). For the example numbers, this translates to about 200 years of+-- continually generating random values at a rate of 10MB/s. data GenAutoReseed a b = GenAutoReseed !a !b !Int !Int instance (CryptoRandomGen a, CryptoRandomGen b) => CryptoRandomGen (GenAutoReseed a b) where@@ -179,22 +222,38 @@ b = helper2 res res = Tagged $ genSeedLength `for` a + genSeedLength `for` b in res- genBytes req (GenAutoReseed a b rs cnt) = do- (res, aNew) <- genBytes req a- gNew <- if (cnt + req) > rs- then do (ent,b') <- genBytes (genSeedLength `for` a) b- a' <- reseed ent aNew- return (GenAutoReseed a' b' rs 0)- else return $ GenAutoReseed aNew b rs (cnt + req)- return (res, gNew)+ genBytes req (GenAutoReseed a b rs cnt) =+ case genBytes req a of+ Left NeedReseed -> do+ (ent,b') <- genBytes (genSeedLength `for` a) b+ a' <- reseed ent a+ (res, aNew) <- genBytes req a'+ return (res,GenAutoReseed aNew b' rs 0)+ Left err -> Left err+ Right (res,aNew) -> do+ gNew <- if (cnt + req) > rs+ then do + (ent,b') <- genBytes (genSeedLength `for` a) b+ a' <- reseed ent aNew+ return (GenAutoReseed a' b' rs 0)+ else return $ GenAutoReseed aNew b rs (cnt + req)+ return (res, gNew) genBytesWithEntropy req entropy (GenAutoReseed a b rs cnt) = do- (res, aNew) <- genBytesWithEntropy req entropy a- gNew <- if (cnt + req) > rs- then do (ent,b') <- genBytes (genSeedLength `for` a) b- a' <- reseed ent aNew- return (GenAutoReseed a' b' rs 0)- else return $ GenAutoReseed aNew b rs (cnt + req)- return (res, gNew)+ case genBytesWithEntropy req entropy a of+ Left NeedReseed -> do+ (ent,b') <- genBytes (genSeedLength `for` a) b+ a' <- reseed ent a+ (res, aNew) <- genBytesWithEntropy req entropy a'+ return (res,GenAutoReseed aNew b' rs 0)+ Left err -> Left err+ Right (res,aNew) -> do+ gNew <- if (cnt + req) > rs+ then do + (ent,b') <- genBytes (genSeedLength `for` a) b+ a' <- reseed ent aNew+ return (GenAutoReseed a' b' rs 0)+ else return $ GenAutoReseed aNew b rs (cnt + req)+ return (res, gNew) reseed ent gen@(GenAutoReseed a b rs _) | genSeedLength `for` gen > B.length ent = Left NotEnoughEntropy | otherwise = do@@ -312,7 +371,6 @@ let new = wrapErr (genBytes (min-B.length bs') g'') g'' bs' = B.take max (B.append bs rs) return (GenBuffered min max new bs')- wrapErr :: Either x y -> g -> Either (x,g) y wrapErr (Left x) g = Left (x,g)
DRBG.cabal view
@@ -1,5 +1,5 @@ name: DRBG-version: 0.1.2+version: 0.1.3 license: BSD3 license-file: LICENSE author: Thomas DuBuisson <thomas.dubuisson@gmail.com>@@ -21,7 +21,7 @@ Library Build-Depends: base >= 4.0 && < 4.4, cereal >= 0.2 && <= 0.4,- bytestring, prettyclass, tagged,+ bytestring, prettyclass, tagged >= 0.2 && < 0.3, crypto-api >= 0.2, cryptohash >= 0.6.1, parallel, mtl == 2.* ghc-options: -O2 hs-source-dirs: