|
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
|