Blame Crypto/Random.hs

Packit 141393
-- |
Packit 141393
-- Module      : Crypto.Random
Packit 141393
-- License     : BSD-style
Packit 141393
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
Packit 141393
-- Stability   : stable
Packit 141393
-- Portability : good
Packit 141393
--
Packit 141393
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
Packit 141393
module Crypto.Random
Packit 141393
    (
Packit 141393
    -- * Deterministic instances
Packit 141393
      ChaChaDRG
Packit 141393
    , SystemDRG
Packit 141393
    , Seed
Packit 141393
    -- * Seed
Packit 141393
    , seedNew
Packit 141393
    , seedFromInteger
Packit 141393
    , seedToInteger
Packit 141393
    , seedFromBinary
Packit 141393
    -- * Deterministic Random class
Packit 141393
    , getSystemDRG
Packit 141393
    , drgNew
Packit 141393
    , drgNewSeed
Packit 141393
    , drgNewTest
Packit 141393
    , withDRG
Packit 141393
    , withRandomBytes
Packit 141393
    , DRG(..)
Packit 141393
    -- * Random abstraction
Packit 141393
    , MonadRandom(..)
Packit 141393
    , MonadPseudoRandom
Packit 141393
    ) where
Packit 141393
Packit 141393
import Crypto.Error
Packit 141393
import Crypto.Random.Types
Packit 141393
import Crypto.Random.ChaChaDRG
Packit 141393
import Crypto.Random.SystemDRG
Packit 141393
import Data.ByteArray (ByteArray, ByteArrayAccess, ScrubbedBytes)
Packit 141393
import qualified Data.ByteArray as B
Packit 141393
import Crypto.Internal.Imports
Packit 141393
Packit 141393
import qualified Crypto.Number.Serialize as Serialize
Packit 141393
Packit 141393
newtype Seed = Seed ScrubbedBytes
Packit 141393
    deriving (ByteArrayAccess)
Packit 141393
Packit 141393
-- Length for ChaCha DRG seed
Packit 141393
seedLength :: Int
Packit 141393
seedLength = 40
Packit 141393
Packit 141393
-- | Create a new Seed from system entropy
Packit 141393
seedNew :: MonadRandom randomly => randomly Seed
Packit 141393
seedNew = Seed `fmap` getRandomBytes seedLength
Packit 141393
Packit 141393
-- | Convert a Seed to an integer
Packit 141393
seedToInteger :: Seed -> Integer
Packit 141393
seedToInteger (Seed b) = Serialize.os2ip b
Packit 141393
Packit 141393
-- | Convert an integer to a Seed
Packit 141393
seedFromInteger :: Integer -> Seed
Packit 141393
seedFromInteger i = Seed $ Serialize.i2ospOf_ seedLength (i `mod` 2^(seedLength * 8))
Packit 141393
Packit 141393
-- | Convert a binary to a seed
Packit 141393
seedFromBinary :: ByteArrayAccess b => b -> CryptoFailable Seed
Packit 141393
seedFromBinary b
Packit 141393
    | B.length b /= 40 = CryptoFailed (CryptoError_SeedSizeInvalid)
Packit 141393
    | otherwise        = CryptoPassed $ Seed $ B.convert b
Packit 141393
Packit 141393
-- | Create a new DRG from system entropy
Packit 141393
drgNew :: MonadRandom randomly => randomly ChaChaDRG
Packit 141393
drgNew = drgNewSeed `fmap` seedNew
Packit 141393
Packit 141393
-- | Create a new DRG from a seed
Packit 141393
drgNewSeed :: Seed -> ChaChaDRG
Packit 141393
drgNewSeed (Seed seed) = initialize seed
Packit 141393
Packit 141393
-- | Create a new DRG from 5 Word64.
Packit 141393
--
Packit 141393
-- This is a convenient interface to create deterministic interface
Packit 141393
-- for quickcheck style testing.
Packit 141393
--
Packit 141393
-- It can also be used in other contexts provided the input
Packit 141393
-- has been properly randomly generated.
Packit 141393
drgNewTest :: (Word64, Word64, Word64, Word64, Word64) -> ChaChaDRG
Packit 141393
drgNewTest = initializeWords
Packit 141393
Packit 141393
-- | Generate @len random bytes and mapped the bytes to the function @f.
Packit 141393
--
Packit 141393
-- This is equivalent to use Control.Arrow 'first' with 'randomBytesGenerate'
Packit 141393
withRandomBytes :: (ByteArray ba, DRG g) => g -> Int -> (ba -> a) -> (a, g)
Packit 141393
withRandomBytes rng len f = (f bs, rng')
Packit 141393
  where (bs, rng') = randomBytesGenerate len rng