Safe Haskell | None |
---|---|
Language | Haskell2010 |
Interface for cryptographically secure random byte generators.
- type RandM = RT VoidMemory
- data RT mem a
- liftMT :: MT mem a -> RT mem a
- randomByteString :: (Memory mem, LengthUnit l) => l -> RT mem ByteString
- class Random a where
- fillRandomBytes :: LengthUnit l => l -> Pointer -> RT mem ()
- unsafeStorableRandom :: (Memory mem, Storable a) => RT mem a
- reseed :: RT mem ()
Cryptographically secure randomness.
The raaz library gives a relatively high level interface to
randomness. The monad RandM
captures a batch of actions that
generate/use cryptographically secure random bytes. In particular,
you can use the functions random
and randomByteString
to
actually generate random elements.
The monad RandM
is an an instance of MonadMemory
and hence can
be run either securely
or insecurely
. Here are some examples.
-- Generate a pair of random Word8's import Raaz import Data.Word main :: IO () main = insecurely rPair >>= print where rPair :: RandM (Word8, Word8) rPair = (,) <$> random <$> random
-- A version of hello world that has gone nuts. Printed in base16 -- to save some terminal grief. main = insecurely who >>= \ w -> putStrLn $ "hello " ++ showBase16 w where who :: RandM ByteString who = randomByteString 10
Some times you need additional memory to keep track of other
stuff. The monad
is meant for such uses. It should be
seen as the analogue of the monad RT
mem
which in addition
allows you to pick cryptographically secure random data. In fact,
the combinator MT
memliftMT
allows you to lift an MT
action to the
corresponding RT
action.
Internal details
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. Raaz uses a stream cipher (chacha20), initialised with a starting random key/iv. The starting seed is then drawn from the system entropy pool.
TODO: For system entropy we use /dev/urandom
on a posix systems
(no windows support yet). Even on posix systems, depending on
underlying operating system, there are better options. The
recommended way to generate randomness on an OpenBSD system is
through the function arc4random
(note that arc4random does not
use rc4 cipher anymore). Recent Linux kernels support the
getrandom
system call which unfortunately is not yet
popular. These system specific calls are better because they take
into consideration many edge cases like for example
/dev/urandom
not being accessible or protection from interrupts
Eventually we will be supporting these calls.
type RandM = RT VoidMemory Source #
The monad for generating cryptographically secure random data.
A batch of actions on the memory element mem
that uses some
randomness.
randomByteString :: (Memory mem, LengthUnit l) => l -> RT mem ByteString Source #
Generate a random byteString.
Types that can be generated randomly
Types that can be generated at random. It might appear that all
storables should be an instance of this class, after all we know
the size of the element why not write that many random bytes. In
fact, this module provides an unsafeStorableRandom
which does
exactly that. However, we do not give a blanket definition for all
storables because for certain refinements of a given type, like for
example, Word8's modulo 10, unsafeStorableRandom
introduces
unacceptable skews.
Random Int Source # | |
Random Int8 Source # | |
Random Int16 Source # | |
Random Int32 Source # | |
Random Int64 Source # | |
Random Word Source # | |
Random Word8 Source # | |
Random Word16 Source # | |
Random Word32 Source # | |
Random Word64 Source # | |
Random KEY Source # | |
Random IV Source # | |
Random IV Source # | |
Random KEY256 Source # | |
Random KEY192 Source # | |
Random KEY128 Source # | |
Random w => Random (BE w) Source # | |
Random w => Random (LE w) Source # | |
(Random a, Random b) => Random (a, b) Source # | |
(Dimension d, Unbox w, Random w) => Random (Tuple d w) Source # | |
(Random a, Random b, Random c) => Random (a, b, c) Source # | |
(Random a, Random b, Random c, Random d) => Random (a, b, c, d) Source # | |
(Random a, Random b, Random c, Random d, Random e) => Random (a, b, c, d, e) Source # | |
Low level access to randomness.
fillRandomBytes :: LengthUnit l => l -> Pointer -> RT mem () Source #
Fill the given input pointer with random bytes.
unsafeStorableRandom :: (Memory mem, Storable a) => RT mem a Source #
Generate a random element. The element picked is crypto-graphically pseudo-random.
This is a helper function that has been exported to simplify the
definition of a Random
instance for Storable
types. However,
there is a reason why we do not give a blanket instance for all
instances Storable
and why this function is unsafe? This function
generates a random element of type a
by generating n
random
bytes where n
is the size of the elements of a
. For instances
that range the entire n
byte space this is fine. However, if the
type is actually a refinement of such a type --- consider for
example,
modulo Word8
10
-- this function generates an
unacceptable skew in the distribution. Hence this function is
prefixed unsafe.
Reseed from the system entropy pool. There is never a need to explicitly seed your generator. The insecurely and securely calls makes sure that your generator is seed before starting. Furthermore, the generator also reseeds after every few GB of random bytes generates. Generating random data from the system entropy is usually an order of magnitude slower than using a fast stream cipher. Reseeding often can slow your program considerably without any additional security advantage.