packages feed

DRBG 0.1.0 → 0.1.1

raw patch · 5 files changed

+73/−30 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Crypto.Random.DRBG: instance (CryptoRandomGen g) => CryptoRandomGen (GenBuffered g)
+ Crypto.Random.DRBG: instance CryptoRandomGen g => CryptoRandomGen (GenBuffered g)
+ Crypto.Random.DRBG: type HashDRBGWith = State
+ Crypto.Random.DRBG: type HmacDRBGWith = State
- Crypto.Random.DRBG.HMAC: generate :: (Hash c d) => State d -> BitLength -> AdditionalInput -> Maybe (RandomBits, State d)
+ Crypto.Random.DRBG.HMAC: generate :: Hash c d => State d -> BitLength -> AdditionalInput -> Maybe (RandomBits, State d)
- Crypto.Random.DRBG.HMAC: instantiate :: (Hash c d) => Entropy -> Nonce -> PersonalizationString -> State d
+ Crypto.Random.DRBG.HMAC: instantiate :: Hash c d => Entropy -> Nonce -> PersonalizationString -> State d
- Crypto.Random.DRBG.HMAC: reseed :: (Hash c d) => State d -> Entropy -> AdditionalInput -> State d
+ Crypto.Random.DRBG.HMAC: reseed :: Hash c d => State d -> Entropy -> AdditionalInput -> State d
- Crypto.Random.DRBG.Hash: seedlen :: (SeedLength h) => Tagged h Int
+ Crypto.Random.DRBG.Hash: seedlen :: SeedLength h => Tagged h Int

Files

+ CHANGELOG view
@@ -0,0 +1,6 @@+New in 0.1.1++* Add HashDRBGWith and HmacDRBGWith+* Allow reseeding of AutoReseed when the second generator to be SystemRandomGen (zero byte reseed of 2nd generator)+* Allow reseeding GenBuffered after an error by tracking the error-inducing generator (and not just the error)+* Fix GenBuffered to buffer properly
Crypto/Random/DRBG.hs view
@@ -11,14 +11,31 @@ and generate some bytes (stepping the generator along the way) one would do:  @-    gen <- newGenIO :: IO HmacDRBG-    let Right (randomBytes, newGen) = genBytes gen 1024+    gen <- newGenIO :: IO HashDRBG+    let Right (randomBytes, newGen) = genBytes 1024 gen @++Selecting the underlying hash algorithm is supporting using *DRBGWith types:++@+    gen <- newGenIO :: IO (HmacDRBGWith SHA224)+@++Composition of generators is supported using two trivial compositions, 'GenXor'+and 'GenAutoReseed'.  Additional compositions can be built by instanciating+a 'CryptoRandomGen' as desired.++@+    sysGen <- getGenSystemRandom+    gen <- newGenIO :: IO (GenBuffered (GenAutoReseed (GenXor AesCntDRBG (HashDRBGWith SHA384)) HmacDRBG))+@+    -}  module Crypto.Random.DRBG 	( HmacDRBG, HashDRBG+	, HmacDRBGWith, HashDRBGWith 	, GenXor 	, GenAutoReseed 	, GenBuffered@@ -41,7 +58,7 @@ import qualified Data.ByteString.Lazy as L import Data.Tagged import Data.Bits (xor)-import Control.Parallel (par)+import Control.Parallel import Control.Monad (liftM) import Control.Monad.Error () -- Either instance import System.IO.Unsafe (unsafeInterleaveIO)@@ -61,10 +78,18 @@ instance H.SeedLength SHA1 where 	seedlen = Tagged 440 --- |An alias for an HmacDRBG generator using SHA512.  This is the recommended generator.+-- |The HMAC DRBG state (of kind * -> *) allowing selection+-- of the underlying hash algorithm (SHA1, SHA224 ... SHA512)+type HmacDRBGWith = M.State++-- |The Hash DRBG state (of kind * -> *) allowing selection+-- of the underlying hash algorithm.+type HashDRBGWith = H.State++-- |An alias for an HMAC DRBG generator using SHA512. type HmacDRBG = M.State SHA512 --- |An Alias for a HashDRBG generator using SHA512.+-- |An Alias for a Hash DRBG generator using SHA512. type HashDRBG = H.State SHA512  newGenAutoReseed :: (CryptoRandomGen a, CryptoRandomGen b) => B.ByteString -> Int -> Either GenError (GenAutoReseed a b)@@ -157,10 +182,14 @@ 				  return (GenAutoReseed a' b' rs 0) 			  else return $ GenAutoReseed aNew b rs (cnt + req) 		return (res, gNew)-	reseed ent (GenAutoReseed a b rs _) = do-		let (b1,b2) = B.splitAt (genSeedLength `for` a) ent-		a' <- reseed b1 a-		b' <- reseed b2 b+	reseed ent gen@(GenAutoReseed a b rs _) +	  | genSeedLength `for` gen > B.length ent = Left NotEnoughEntropy+	  | otherwise = do+		let (e1,e2) = B.splitAt (genSeedLength `for` a) ent+		a' <- reseed e1 a+		b' <- if B.length e2 /= 0+			then reseed e2 b+			else return b 		return $ GenAutoReseed a' b' rs 0  -- |@g :: GenXor a b@ generates bytes with sub-generators a and b @@ -205,12 +234,8 @@ 		return (GenXor a' b')  -- |@g :: GenBuffered a@ is a generator of type @a@ that attempts to--- maintain a buffer of random values size > 1MB and < 5MB at any time.------ Because of the way in which the buffer is computed (at idle times) and--- information on the previous generator is lost, it basically is not possible--- to reseed this generator after a GenError.-data GenBuffered g = GenBuffered (Either GenError (B.ByteString, g)) {-# UNPACK #-} !B.ByteString+-- maintain a buffer of random values size >= 1MB and <= 5MB at any time.+data GenBuffered g = GenBuffered (Either (GenError, g) (B.ByteString, g)) {-# UNPACK #-} !B.ByteString  proxyToGenBuffered :: Proxy g -> Proxy (Either GenError (GenBuffered g)) proxyToGenBuffered = const Proxy@@ -224,8 +249,8 @@ 	newGen bs = do 		g <- newGen bs 		(rs,g') <- genBytes bufferMinSize g-		let new = genBytes bufferMinSize g'-		return (GenBuffered new rs)+		let new = wrapErr (genBytes bufferMinSize g') g'+		(let !_ = rs in ()) `par` return (GenBuffered new rs) 	genSeedLength = 		let a = help res 		    res = Tagged $ genSeedLength `for` a@@ -237,26 +262,35 @@ 		| remSize >= bufferMinSize =  Right (B.take req bs, GenBuffered g (B.drop req bs)) 		| B.length bs < bufferMinSize = 			case g of-				Left err  -> Left err+				Left (err,_)  -> Left err 				Right g   -> Left (GenErrorOther "Buffering generator failed to buffer properly - unknown reason") 		| req > B.length bs = Left RequestedTooManyBytes 		| remSize < bufferMinSize = 			case g of-				Left err -> Left err -- We could satisfy _this_ request and fail after the buffer runs out, but why bother?+				Left (err,_) -> Left err 				Right (rnd, gen) ->-					let new = genBytes bufferMinSize gen-					in (eval new) `par` (genBytes req (GenBuffered new (B.append bs rnd)))+					let new = wrapErr (genBytes bufferMinSize gen) gen+					    (rs,rem) = B.splitAt req bs+					in (eval new) `par` Right (rs, GenBuffered new (B.append rem rnd)) 		| otherwise = Left $ GenErrorOther "Buffering generator hit an impossible case.  Please inform DRBG maintainer" 	  where 	  remSize = B.length bs - req 	genBytesWithEntropy req ent g = reseed ent g >>= \gen -> genBytes req gen 	reseed ent (GenBuffered g bs) = do-		(rs, g') <- g+		let (rs, g') =+		      case g of+			Left (_,g') -> (B.empty, g')+			Right (rs, g') -> (rs, g') 		g'' <- reseed ent g'-		let new = genBytes bufferMinSize g''+		let new = wrapErr (genBytes bufferMinSize g'') g'' 		    bs' = B.take bufferMaxSize (B.append bs rs) 		return (GenBuffered new bs') +wrapErr :: Either x y -> g -> Either (x,g) y+wrapErr (Left x) g = Left (x,g)+wrapErr (Right r) _ = Right r++-- |Force evaluation for use by GenBuffered. eval :: Either x (B.ByteString, g) -> Either x (B.ByteString, g) eval (Left x) = Left x eval (Right (g,bs)) = bs `seq` (g `seq` (Right (g, bs)))@@ -283,7 +317,7 @@ 	liftM (GenSysRandom . L.fromChunks) getBS  instance CryptoRandomGen GenSystemRandom where-	newGen _ = Left $ GenErrorOther "SystemRandomGen isn't a semantically correct generator.  Tell your developer to use 'Crypto.Random.DRBG.getGenSystemRandom' instead of 'Crypto.Random.newGen'"+	newGen _ = Left $ GenErrorOther "SystemRandomGen isn't a semanticly correct generator.  Tell your developer to use 'Crypto.Random.DRBG.getGenSystemRandom' instead of 'Crypto.Random.newGen'" 	genSeedLength = Tagged 0 	genBytes req (GenSysRandom bs) = 		let reqI = fromIntegral req@@ -293,6 +327,12 @@ 			then Right (B.concat $ L.toChunks rnd, GenSysRandom rest) 			else Left $ GenErrorOther "Error obtaining enough bytes from system random for given request" 	reseed _ _ = Left $ GenErrorOther "SystemRandomGen isn't a semantically correct generator. Don't use 'WithEntropy'."++split :: CryptoRandomGen g => g -> Either GenError (g,g)+split g = do+	(ent,g') <- genBytes (genSeedLength `for` g) g+	new <- newGen ent+	return (g', new)  -- |zipWith xor + Pack -- As a result of rewrite rules, this should automatically be optimized (at compile time) 
Crypto/Random/DRBG/HMAC.hs view
@@ -15,7 +15,6 @@ import Crypto.HMAC import Crypto.Types import Crypto.Random.DRBG.Types-import qualified Data.Binary as Bin  type Key = B.ByteString type Value = B.ByteString
Crypto/Random/DRBG/Hash.hs view
@@ -15,7 +15,6 @@ import Crypto.Random.DRBG.HashDF import Crypto.Classes import Data.Serialize (encode)-import qualified Data.Binary as Bin import Data.Bits (shiftR, shiftL) import Data.Tagged 
DRBG.cabal view
@@ -1,5 +1,5 @@ name:		DRBG-version:	0.1.0+version:	0.1.1 license:	BSD3 license-file:	LICENSE author:		Thomas DuBuisson <thomas.dubuisson@gmail.com>@@ -11,7 +11,7 @@ build-type:	Simple cabal-version:	>= 1.6 tested-with:	GHC == 6.10.1-Data-Files: Test/HMAC_DRBG.txt Test/Hash_DRBG.txt Test/CTR_DRBG.txt Test/Dual_EC_DRBG.txt+Data-Files: Test/HMAC_DRBG.txt Test/Hash_DRBG.txt Test/CTR_DRBG.txt Test/Dual_EC_DRBG.txt CHANGELOG extra-source-files:   Test/HMAC_DRBG.txt Test/Hash_DRBG.txt Test/CTR_DRBG.txt Test/Dual_EC_DRBG.txt @@ -19,10 +19,9 @@   description: Build a program to test the DRBG library   default: False - Library   Build-Depends: base >= 4.0 && < 4.4, cereal >= 0.2 && <= 0.4,-                 bytestring, prettyclass, binary, tagged,+                 bytestring, prettyclass, tagged,                  crypto-api >= 0.2, cryptohash >= 0.6.1, parallel, mtl == 2.*   ghc-options: -O2   hs-source-dirs: