Portability | portable |
---|---|
Stability | beta |
Maintainer | Thomas.DuBuisson@gmail.com |
Safe Haskell | None |
This module is the convenience interface for the DRBG (NIST standardized
number-theoretically secure random number generator). Everything is setup
for using the crypto-api CryptoRandomGen
type class.
To instantiate the base types of HmacDRBG
, HashDRBG
, or GenAES
just use
the CryptoRandomGen
primitives of newGen
or newGenIO
.
For example, to seed a new generator with the system secure random
(Entropy
) and generate some bytes (stepping the generator along
the way) one would do:
gen <- newGenIO :: IO HashDRBG let Right (randomBytes, newGen) = genBytes 1024 gen
or the same thing with your own entropy (throwing exceptions instead of dealing
with Either
this time):
let gen = throwLeft (newGen entropy) (bytes,gen') = throwLeft (genBytes 1024 gen) in ...
Selecting the underlying hash algorithm is supporting using *DRBGWith types:
gen <- newGenIO :: IO (HmacDRBGWith SHA224)
There are several modifiers that allow you to compose generators together, producing
generators with modified security, reseed, and performance properties. GenXor
will xor the random bytes of two generators. GenBuffered
will spark off work
to generate several megabytes of random data and keep that data buffered for
quick use. GenAutoReseed
will use one generator to automatically reseed
another after every 32 kilobytes of requested randoms.
For a complex example, here is a generator that buffers several megabytes of random values which are an Xor of AES with a SHA384 hash that are each reseeded every 32kb with the output of a SHA512 HMAC generator. (Not to claim this has any enhanced security properties, but just to show the composition can be nested).
gen <- newGenIO :: IO (GenBuffered (GenAutoReseed (GenXor AesCntDRBG (HashDRBGWith SHA384)) HmacDRBG))
- type HmacDRBG = State SHA512
- type HashDRBG = State SHA512
- type CtrDRBG = State AESKey
- type HmacDRBGWith = State
- type HashDRBGWith = State
- type CtrDRBGWith = State
- data GenXor a b
- data GenBuffered g
- data GenAutoReseed a b
- newGenAutoReseed :: (CryptoRandomGen a, CryptoRandomGen b) => ByteString -> Word64 -> Either GenError (GenAutoReseed a b)
- newGenAutoReseedIO :: (CryptoRandomGen a, CryptoRandomGen b) => Word64 -> IO (GenAutoReseed a b)
- module Crypto.Random
- module Crypto.Types
Basic Hash-based Generators
type HmacDRBGWith = StateSource
The HMAC DRBG state (of kind * -> *) allowing selection of the underlying hash algorithm (SHA1, SHA224 ... SHA512)
type HashDRBGWith = StateSource
The Hash DRBG state (of kind * -> *) allowing selection of the underlying hash algorithm.
type CtrDRBGWith = StateSource
The Hash DRBG state (of kind * -> *) allowing selection of the underlying cipher algorithm.
CryptoRandomGen Transformers
g :: GenXor a b
generates bytes with sub-generators a and b
and exclusive-or's the outputs to produce the resulting bytes.
(CryptoRandomGen a, CryptoRandomGen b) => CryptoRandomGen (GenXor a b) |
data GenBuffered g Source
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.
CryptoRandomGen g => CryptoRandomGen (GenBuffered g) |
data GenAutoReseed a b Source
g :: GenAutoReseed a b
is a generator of type a that gets
automatically reseeded by generator b upon every 32kB generated.
reseed g ent
will reseed both the component generators by
breaking ent up into two parts determined by the genSeedLength of each generator.
genBytes
will generate the requested bytes with generator a
and reseed a
using generator b
if there has been 32KB of generated data since the last reseed.
Note a request for > 32KB of data will be filled in one request to generator a
before
a
is reseeded by b
.
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 byte. For the example numbers this translates to
about 200 years of continually generating random values at a rate of 10MB/s.
(CryptoRandomGen a, CryptoRandomGen b) => CryptoRandomGen (GenAutoReseed a b) |
AutoReseed generator construction with custom reseed interval
newGenAutoReseed :: (CryptoRandomGen a, CryptoRandomGen b) => ByteString -> Word64 -> Either GenError (GenAutoReseed a b)Source
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^41
bytes of randomly generated data. That's
2^49 terabytes of random values (128 byte reseeds every 2^48 bytes generated).
newGenAutoReseedIO :: (CryptoRandomGen a, CryptoRandomGen b) => Word64 -> IO (GenAutoReseed a b)Source
newGenAutoReseedIO i
creates a new GenAutoReseed
with a custom
interval of i
bytes, using the system random number generator as a seed.
See newGenAutoReseed
.
Helper Re-exports
module Crypto.Random
module Crypto.Types