Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module implements the pseudo-random generator using the fast key erasure technique (https://blog.cr.yp.to/20170723-random.html) parameterised on the signatures Implementation and Entropy. This technique is the underlying algorithm used in systems like OpenBSD in their implementation of arc4random.
WARNING: These details are only for developers and reviewers of raaz the library. A casual user should not be looking into this module this let alone tweaking the code here.
Synopsis
- data RandomState
- reseed :: RandomState -> IO ()
- fillRandomBytes :: (LengthUnit l, Pointer ptr) => l -> Dest (ptr a) -> RandomState -> IO ()
- entropySource :: String
- csprgName :: String
- csprgDescription :: String
Pseudo-random generator
Generating unpredictable stream of bytes is one task that has burnt the fingers of a lot of programmers. Unfortunately, getting it correct is something of a black art. We give the internal details of the cryptographic pseudo-random generator used in raaz. Note that none of the details here are accessible or tuneable by the user. This is a deliberate design choice to insulate the user from things that are pretty easy to mess up.
The pseudo-random generator is essentially a primitive that supports the generation of multiple blocks of data once its internals are set. The overall idea is to set the internals from a truly random source and then use the primitive to expand the internal state into pseudo-random bytes. However, there are tricky issues regarding forward security that will make such a simplistic algorithm insecure. Besides, where do we get our truly random seed to begin the process?
We more or less follow the fast key erasure technique (https://blog.cr.yp.to/20170723-random.html) which is used in the arc4random implementation in OpenBSD. The two main steps in the generation of the required random bytes are the following:
- Seeding:
- Setting the internal state of a primitive. We use the
getEntropy
function for this purposes. - Sampling:
- Pre-computing a few blocks using
randomBlocks
that will later on be used to satisfy satisfy the requests for random bytes.
Instead of running the randomBlocks
for every request, we
generate RandomBufferSize
blocks of random blocks in an auxiliary
buffer and satisfy requests for random bytes from this buffer. To
ensure that the compromise of the PRG state does not compromise the
random data already generated and given out, we do the following.
- After generating
RandomBufferSize
blocks of data in the auxiliary buffer, we immediately re-initialise the internals of the primitive from the auxiliary buffer. This ensures that there is no way to know which internal state was used to generate the current contents in the auxiliary buffer. - Every use of data from the auxiliary buffer, whether it is to satisfy a request for random bytes or to reinitialise the internals in step 1 is wiped out immediately.
Assuming the security of the entropy source given by the
getEntropy
and the random block generator given by the
randomBlocks
we have the following security guarantee.
- Security Guarantee:
- At any point of time, a compromise of the cipher state (i.e. key iv pair) and/or the auxiliary buffer does not reveal the random data that is given out previously.
data RandomState Source #
Memory for storing the csprg state.
Instances
Memory RandomState Source # | |
Defined in PRGenerator memoryAlloc :: Alloc RandomState unsafeToPointer :: RandomState -> Ptr Word8 | |
WriteAccessible RandomState Source # | Gives access into the internals of the associated cipher. |
Defined in PRGenerator writeAccess :: RandomState -> [Access] afterWriteAdjustment :: RandomState -> IO () | |
ByteSource RandomState Source # | |
Defined in PRGenerator fillBytes :: BYTES Int -> RandomState -> Ptr a -> IO (FillResult RandomState) |
reseed :: RandomState -> IO () Source #
Reseed the state from the system entropy pool. The CSPRG interface automatically takes care of reseeding from the entropy pool at regular intervals and the user almost never needs to use this.
fillRandomBytes :: (LengthUnit l, Pointer ptr) => l -> Dest (ptr a) -> RandomState -> IO () Source #
Fill a buffer pointed by the given pointer with random bytes.
Information about the cryptographic generator.
entropySource :: String #
csprgDescription :: String Source #
A short description of the csprg.