Portability | portable |
---|---|

Stability | beta |

Maintainer | Thomas.DuBuisson@gmail.com |

This module is for instantiating cryptographically strong
determinitic random bit generators (DRBGs, aka PRNGs) For the simple
use case of using the system random number generator
(`System.Crypto.Random`

) to seed the DRBG:

g <- newGenIO

Users needing to provide their own entropy can call `newGen`

directly

entropy <- getEntropy nrBytes let generator = newGen entropy

- class CryptoRandomGen g where
- newGen :: ByteString -> Either GenError g
- genSeedLength :: Tagged g ByteLength
- genBytes :: ByteLength -> g -> Either GenError (ByteString, g)
- genBytesWithEntropy :: ByteLength -> ByteString -> g -> Either GenError (ByteString, g)
- reseed :: ByteString -> g -> Either GenError g
- newGenIO :: IO g

- data GenError
- splitGen :: CryptoRandomGen g => g -> Either GenError (g, g)
- data SystemRandom

# Basic Interface

class CryptoRandomGen g whereSource

A class of random bit generators that allows for the possibility of failure, reseeding, providing entropy at the same time as requesting bytes

Minimum complete definition: `newGen`

, `genSeedLength`

, `genBytes`

,
`reseed`

.

newGen :: ByteString -> Either GenError gSource

Instantiate a new random bit generator. The provided
bytestring should be of length >= genSeedLength. If the
bytestring is shorter then the call may fail (suggested
error: `NotEnoughEntropy`

). If the bytestring is of
sufficent length the call should always succeed.

genSeedLength :: Tagged g ByteLengthSource

Length of input entropy necessary to instantiate or reseed a generator

genBytes :: ByteLength -> g -> Either GenError (ByteString, g)Source

`genBytes len g`

generates a random ByteString of length
`len`

and new generator. The MonadCryptoRandom package
has routines useful for converting the ByteString to
commonly needed values (but cereal or other
deserialization libraries would also work).

This routine can fail if the generator has gone too long
without a reseed (usually this is in the ball-park of 2^48
requests). Suggested error in this cases is `NeedReseed`

genBytesWithEntropy :: ByteLength -> ByteString -> g -> Either GenError (ByteString, g)Source

`genBytesWithEntropy g i entropy`

generates `i`

random
bytes and use the additional input `entropy`

in the
generation of the requested data to increase the confidence
our generated data is a secure random stream.

Some generators use `entropy`

to perturb the state of the
generator, meaning:

(_,g2') <- genBytesWithEntropy len g1 ent (_,g2 ) <- genBytes len g1 g2 /= g2'

But this is not required.

Default:

genBytesWithEntropy g bytes entropy = xor entropy (genBytes g bytes)

reseed :: ByteString -> g -> Either GenError gSource

If the generator has produced too many random bytes on its
existing seed it will throw `NeedReseed`

. In that case,
reseed the generator using this function and a new
high-entropy seed of length >= `genSeedLength`

. Using
bytestrings that are too short can result in an error
(`NotEnoughEntropy`

).

By default this uses System.Crypto.Random to obtain
entropy for `newGen`

.

Generator failures should always return the appropriate GenError.

GenErrorOther String | Misc |

RequestedTooManyBytes | Requested more bytes than a single pass can generate (The maximum request is generator dependent) |

RangeInvalid | When using |

NeedReseed | Some generators cease operation after too high a count without a reseed (ex: NIST SP 800-90) |

NotEnoughEntropy | For instantiating new generators (or reseeding) |

NeedsInfiniteSeed | This generator can not be
instantiated or reseeded with a
finite seed (ex: |

# Helper functions and expanded interface

splitGen :: CryptoRandomGen g => g -> Either GenError (g, g)Source

While the safety and wisdom of a splitting function depends on the properties of the generator being split, several arguments from informed people indicate such a function is safe for NIST SP 800-90 generators. (see libraries@haskell.org discussion around Sept, Oct 2010)

# Instances

data SystemRandom Source

Not that it is technically correct as an instance of
`CryptoRandomGen`

, but simply because it's a reasonable engineering
choice here is a CryptoRandomGen which streams the system
randoms. Take note: