{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
-- | Support for generation of cryptographically secure random numbers.
--
-- This is a convenience layer on top of "System.Entropy", which allows you to
-- pull random values by means of the class 'CryptoRNG', while keeping the state
-- of the random number generator (RNG) inside a monad. The state is protected
-- by an MVar, which means that concurrent generation of random values from
-- several threads works straight out of the box.
module Crypto.RNG
  ( -- * CryptoRNG class
    module Crypto.RNG.Class
    -- * Monad transformer for carrying rng state
  , CryptoRNGT
  , mapCryptoRNGT
  , runCryptoRNGT
  , withCryptoRNGState
    -- * Instantiation of the initial RNG state
  , CryptoRNGState
  , newCryptoRNGState
  , newCryptoRNGStateSized
    -- ** Low-level utils
  , randomBytesIO
  ) where

import Control.Applicative
import Control.Concurrent
import Control.Monad
import Control.Monad.Base
import Control.Monad.Catch
import Control.Monad.Except
import Control.Monad.Reader
import Control.Monad.Trans.Control
import Data.Bits
import Data.ByteString (ByteString)
import Data.Primitive.SmallArray
import System.Entropy
import qualified Data.ByteString as BS
import qualified Data.ByteString.Short as SBS
import qualified System.Random.Stateful as R

import Crypto.RNG.Class

-- | The random number generator state.
data CryptoRNGState = CryptoRNGState !Int !(SmallArray (MVar Buffer))

-- | A buffer of random bytes for immediate consumption.
newtype Buffer = Buffer { Buffer -> ByteString
bytes :: BS.ByteString }

instance R.StatefulGen CryptoRNGState IO where
  uniformWord8 :: CryptoRNGState -> IO Word8
uniformWord8  CryptoRNGState
st = ByteString -> Word8
forall a. (Bits a, Integral a) => ByteString -> a
mkWord (ByteString -> Word8) -> IO ByteString -> IO Word8
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> CryptoRNGState -> IO ByteString
randomBytesIO Int
1 CryptoRNGState
st
  uniformWord16 :: CryptoRNGState -> IO Word16
uniformWord16 CryptoRNGState
st = ByteString -> Word16
forall a. (Bits a, Integral a) => ByteString -> a
mkWord (ByteString -> Word16) -> IO ByteString -> IO Word16
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> CryptoRNGState -> IO ByteString
randomBytesIO Int
2 CryptoRNGState
st
  uniformWord32 :: CryptoRNGState -> IO Word32
uniformWord32 CryptoRNGState
st = ByteString -> Word32
forall a. (Bits a, Integral a) => ByteString -> a
mkWord (ByteString -> Word32) -> IO ByteString -> IO Word32
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> CryptoRNGState -> IO ByteString
randomBytesIO Int
4 CryptoRNGState
st
  uniformWord64 :: CryptoRNGState -> IO Word64
uniformWord64 CryptoRNGState
st = ByteString -> Word64
forall a. (Bits a, Integral a) => ByteString -> a
mkWord (ByteString -> Word64) -> IO ByteString -> IO Word64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> CryptoRNGState -> IO ByteString
randomBytesIO Int
8 CryptoRNGState
st
  uniformShortByteString :: Int -> CryptoRNGState -> IO ShortByteString
uniformShortByteString Int
n CryptoRNGState
st = ByteString -> ShortByteString
SBS.toShort (ByteString -> ShortByteString)
-> IO ByteString -> IO ShortByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> CryptoRNGState -> IO ByteString
randomBytesIO Int
n CryptoRNGState
st

mkWord :: (Bits a, Integral a) => ByteString -> a
mkWord :: ByteString -> a
mkWord ByteString
bs = (a -> Word8 -> a) -> a -> ByteString -> a
forall a. (a -> Word8 -> a) -> a -> ByteString -> a
BS.foldl' (\a
acc Word8
w -> a -> Int -> a
forall a. Bits a => a -> Int -> a
shiftL a
acc Int
8 a -> a -> a
forall a. Bits a => a -> a -> a
.|. Word8 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w) a
0 ByteString
bs

----------------------------------------

-- | Create a new 'CryptoRNGState' based on system entropy with a buffer size of
-- 32KB.
--
-- One buffer per capability is created.
newCryptoRNGState :: MonadIO m => m CryptoRNGState
newCryptoRNGState :: m CryptoRNGState
newCryptoRNGState = Int -> m CryptoRNGState
forall (m :: * -> *). MonadIO m => Int -> m CryptoRNGState
newCryptoRNGStateSized (Int -> m CryptoRNGState) -> Int -> m CryptoRNGState
forall a b. (a -> b) -> a -> b
$ Int
32 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
1024

-- | Create a new 'CryptoRNGState' based on system entropy with buffers of
-- specified size.
--
-- One buffer per capability is created.
newCryptoRNGStateSized
  :: MonadIO m
  => Int -- ^ Buffer size.
  -> m CryptoRNGState
newCryptoRNGStateSized :: Int -> m CryptoRNGState
newCryptoRNGStateSized Int
maxBufSize = IO CryptoRNGState -> m CryptoRNGState
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO CryptoRNGState -> m CryptoRNGState)
-> IO CryptoRNGState -> m CryptoRNGState
forall a b. (a -> b) -> a -> b
$ do
  Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
maxBufSize Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
    [Char] -> IO ()
forall a. HasCallStack => [Char] -> a
error [Char]
"Buffer size must be larger than 0"
  Int
n <- IO Int
getNumCapabilities
  [MVar Buffer]
bufs <- Int -> IO (MVar Buffer) -> IO [MVar Buffer]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
n (IO (MVar Buffer) -> IO [MVar Buffer])
-> (Buffer -> IO (MVar Buffer)) -> Buffer -> IO [MVar Buffer]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Buffer -> IO (MVar Buffer)
forall a. a -> IO (MVar a)
newMVar (Buffer -> IO [MVar Buffer]) -> Buffer -> IO [MVar Buffer]
forall a b. (a -> b) -> a -> b
$ ByteString -> Buffer
Buffer ByteString
BS.empty
  CryptoRNGState -> IO CryptoRNGState
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CryptoRNGState -> IO CryptoRNGState)
-> CryptoRNGState -> IO CryptoRNGState
forall a b. (a -> b) -> a -> b
$ Int -> SmallArray (MVar Buffer) -> CryptoRNGState
CryptoRNGState Int
maxBufSize (Int -> [MVar Buffer] -> SmallArray (MVar Buffer)
forall a. Int -> [a] -> SmallArray a
smallArrayFromListN Int
n [MVar Buffer]
bufs)

-- | Generate a number of cryptographically secure random bytes.
randomBytesIO :: Int -> CryptoRNGState -> IO ByteString
randomBytesIO :: Int -> CryptoRNGState -> IO ByteString
randomBytesIO Int
n (CryptoRNGState Int
maxBufSize SmallArray (MVar Buffer)
bufs) = do
  (Int
cid, Bool
_) <- ThreadId -> IO (Int, Bool)
threadCapability (ThreadId -> IO (Int, Bool)) -> IO ThreadId -> IO (Int, Bool)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO ThreadId
myThreadId
  let mbuf :: MVar Buffer
mbuf = SmallArray (MVar Buffer)
bufs SmallArray (MVar Buffer) -> Int -> MVar Buffer
forall a. SmallArray a -> Int -> a
`indexSmallArray` (Int
cid Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` SmallArray (MVar Buffer) -> Int
forall a. SmallArray a -> Int
sizeofSmallArray SmallArray (MVar Buffer)
bufs)
  MVar Buffer -> (Buffer -> IO (Buffer, ByteString)) -> IO ByteString
forall a b. MVar a -> (a -> IO (a, b)) -> IO b
modifyMVar MVar Buffer
mbuf ((Buffer -> IO (Buffer, ByteString)) -> IO ByteString)
-> (Buffer -> IO (Buffer, ByteString)) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Buffer
buf -> do
    -- Unroll the first step of 'generateBytes' as the vast majority of time
    -- it's enough to get the full amount of requested bytes.
    let (ByteString
r, ByteString
newBytes) = Int -> ByteString -> (ByteString, ByteString)
BS.splitAt Int
n (Buffer -> ByteString
bytes Buffer
buf)
    let k :: Int
k = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- ByteString -> Int
BS.length ByteString
r
    if Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0
      then ByteString
newBytes ByteString -> IO (Buffer, ByteString) -> IO (Buffer, ByteString)
`seq` (Buffer, ByteString) -> IO (Buffer, ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Buffer
Buffer ByteString
newBytes, ByteString
r)
      else do
        ([ByteString]
rs, Buffer
newBuf) <- Int -> Buffer -> Int -> [ByteString] -> IO ([ByteString], Buffer)
generateBytes Int
maxBufSize Buffer
buf Int
k [ByteString
r]
        (Buffer, ByteString) -> IO (Buffer, ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Buffer
newBuf, [ByteString] -> ByteString
BS.concat [ByteString]
rs)

generateBytes
  :: Int
  -> Buffer
  -> Int
  -> [BS.ByteString]
  -> IO ([BS.ByteString], Buffer)
generateBytes :: Int -> Buffer -> Int -> [ByteString] -> IO ([ByteString], Buffer)
generateBytes Int
maxBufSize Buffer
buf Int
n [ByteString]
acc = do
  (ByteString
r, ByteString
newBytes) <- Int -> ByteString -> (ByteString, ByteString)
BS.splitAt Int
n (ByteString -> (ByteString, ByteString))
-> IO ByteString -> IO (ByteString, ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> if ByteString -> Bool
BS.null (Buffer -> ByteString
bytes Buffer
buf)
                                    then Int -> IO ByteString
getEntropy Int
maxBufSize
                                    else ByteString -> IO ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Buffer -> ByteString
bytes Buffer
buf)
  let newBuf :: Buffer
newBuf = ByteString -> Buffer
Buffer ByteString
newBytes
      k :: Int
k = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- ByteString -> Int
BS.length ByteString
r
  Buffer
newBuf Buffer -> IO ([ByteString], Buffer) -> IO ([ByteString], Buffer)
`seq` if Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0
    then ([ByteString], Buffer) -> IO ([ByteString], Buffer)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString
r ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
acc, Buffer
newBuf)
    else Int -> Buffer -> Int -> [ByteString] -> IO ([ByteString], Buffer)
generateBytes Int
maxBufSize Buffer
newBuf Int
k (ByteString
r ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
acc)

----------------------------------------

-- | Monad transformer with RNG state.
newtype CryptoRNGT m a = CryptoRNGT { CryptoRNGT m a -> ReaderT CryptoRNGState m a
unCryptoRNGT :: ReaderT CryptoRNGState m a }
  deriving ( Applicative (CryptoRNGT m)
CryptoRNGT m a
Applicative (CryptoRNGT m)
-> (forall a. CryptoRNGT m a)
-> (forall a. CryptoRNGT m a -> CryptoRNGT m a -> CryptoRNGT m a)
-> (forall a. CryptoRNGT m a -> CryptoRNGT m [a])
-> (forall a. CryptoRNGT m a -> CryptoRNGT m [a])
-> Alternative (CryptoRNGT m)
CryptoRNGT m a -> CryptoRNGT m a -> CryptoRNGT m a
CryptoRNGT m a -> CryptoRNGT m [a]
CryptoRNGT m a -> CryptoRNGT m [a]
forall a. CryptoRNGT m a
forall a. CryptoRNGT m a -> CryptoRNGT m [a]
forall a. CryptoRNGT m a -> CryptoRNGT m a -> CryptoRNGT m a
forall (f :: * -> *).
Applicative f
-> (forall a. f a)
-> (forall a. f a -> f a -> f a)
-> (forall a. f a -> f [a])
-> (forall a. f a -> f [a])
-> Alternative f
forall (m :: * -> *). Alternative m => Applicative (CryptoRNGT m)
forall (m :: * -> *) a. Alternative m => CryptoRNGT m a
forall (m :: * -> *) a.
Alternative m =>
CryptoRNGT m a -> CryptoRNGT m [a]
forall (m :: * -> *) a.
Alternative m =>
CryptoRNGT m a -> CryptoRNGT m a -> CryptoRNGT m a
many :: CryptoRNGT m a -> CryptoRNGT m [a]
$cmany :: forall (m :: * -> *) a.
Alternative m =>
CryptoRNGT m a -> CryptoRNGT m [a]
some :: CryptoRNGT m a -> CryptoRNGT m [a]
$csome :: forall (m :: * -> *) a.
Alternative m =>
CryptoRNGT m a -> CryptoRNGT m [a]
<|> :: CryptoRNGT m a -> CryptoRNGT m a -> CryptoRNGT m a
$c<|> :: forall (m :: * -> *) a.
Alternative m =>
CryptoRNGT m a -> CryptoRNGT m a -> CryptoRNGT m a
empty :: CryptoRNGT m a
$cempty :: forall (m :: * -> *) a. Alternative m => CryptoRNGT m a
$cp1Alternative :: forall (m :: * -> *). Alternative m => Applicative (CryptoRNGT m)
Alternative, Functor (CryptoRNGT m)
a -> CryptoRNGT m a
Functor (CryptoRNGT m)
-> (forall a. a -> CryptoRNGT m a)
-> (forall a b.
    CryptoRNGT m (a -> b) -> CryptoRNGT m a -> CryptoRNGT m b)
-> (forall a b c.
    (a -> b -> c)
    -> CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m c)
-> (forall a b. CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m b)
-> (forall a b. CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m a)
-> Applicative (CryptoRNGT m)
CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m b
CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m a
CryptoRNGT m (a -> b) -> CryptoRNGT m a -> CryptoRNGT m b
(a -> b -> c) -> CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m c
forall a. a -> CryptoRNGT m a
forall a b. CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m a
forall a b. CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m b
forall a b.
CryptoRNGT m (a -> b) -> CryptoRNGT m a -> CryptoRNGT m b
forall a b c.
(a -> b -> c) -> CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
forall (m :: * -> *). Applicative m => Functor (CryptoRNGT m)
forall (m :: * -> *) a. Applicative m => a -> CryptoRNGT m a
forall (m :: * -> *) a b.
Applicative m =>
CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m a
forall (m :: * -> *) a b.
Applicative m =>
CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m b
forall (m :: * -> *) a b.
Applicative m =>
CryptoRNGT m (a -> b) -> CryptoRNGT m a -> CryptoRNGT m b
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c) -> CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m c
<* :: CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m a
$c<* :: forall (m :: * -> *) a b.
Applicative m =>
CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m a
*> :: CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m b
$c*> :: forall (m :: * -> *) a b.
Applicative m =>
CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m b
liftA2 :: (a -> b -> c) -> CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m c
$cliftA2 :: forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c) -> CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m c
<*> :: CryptoRNGT m (a -> b) -> CryptoRNGT m a -> CryptoRNGT m b
$c<*> :: forall (m :: * -> *) a b.
Applicative m =>
CryptoRNGT m (a -> b) -> CryptoRNGT m a -> CryptoRNGT m b
pure :: a -> CryptoRNGT m a
$cpure :: forall (m :: * -> *) a. Applicative m => a -> CryptoRNGT m a
$cp1Applicative :: forall (m :: * -> *). Applicative m => Functor (CryptoRNGT m)
Applicative, a -> CryptoRNGT m b -> CryptoRNGT m a
(a -> b) -> CryptoRNGT m a -> CryptoRNGT m b
(forall a b. (a -> b) -> CryptoRNGT m a -> CryptoRNGT m b)
-> (forall a b. a -> CryptoRNGT m b -> CryptoRNGT m a)
-> Functor (CryptoRNGT m)
forall a b. a -> CryptoRNGT m b -> CryptoRNGT m a
forall a b. (a -> b) -> CryptoRNGT m a -> CryptoRNGT m b
forall (m :: * -> *) a b.
Functor m =>
a -> CryptoRNGT m b -> CryptoRNGT m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> CryptoRNGT m a -> CryptoRNGT m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> CryptoRNGT m b -> CryptoRNGT m a
$c<$ :: forall (m :: * -> *) a b.
Functor m =>
a -> CryptoRNGT m b -> CryptoRNGT m a
fmap :: (a -> b) -> CryptoRNGT m a -> CryptoRNGT m b
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> CryptoRNGT m a -> CryptoRNGT m b
Functor, Applicative (CryptoRNGT m)
a -> CryptoRNGT m a
Applicative (CryptoRNGT m)
-> (forall a b.
    CryptoRNGT m a -> (a -> CryptoRNGT m b) -> CryptoRNGT m b)
-> (forall a b. CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m b)
-> (forall a. a -> CryptoRNGT m a)
-> Monad (CryptoRNGT m)
CryptoRNGT m a -> (a -> CryptoRNGT m b) -> CryptoRNGT m b
CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m b
forall a. a -> CryptoRNGT m a
forall a b. CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m b
forall a b.
CryptoRNGT m a -> (a -> CryptoRNGT m b) -> CryptoRNGT m b
forall (m :: * -> *). Monad m => Applicative (CryptoRNGT m)
forall (m :: * -> *) a. Monad m => a -> CryptoRNGT m a
forall (m :: * -> *) a b.
Monad m =>
CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m b
forall (m :: * -> *) a b.
Monad m =>
CryptoRNGT m a -> (a -> CryptoRNGT m b) -> CryptoRNGT m b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> CryptoRNGT m a
$creturn :: forall (m :: * -> *) a. Monad m => a -> CryptoRNGT m a
>> :: CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
CryptoRNGT m a -> CryptoRNGT m b -> CryptoRNGT m b
>>= :: CryptoRNGT m a -> (a -> CryptoRNGT m b) -> CryptoRNGT m b
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
CryptoRNGT m a -> (a -> CryptoRNGT m b) -> CryptoRNGT m b
$cp1Monad :: forall (m :: * -> *). Monad m => Applicative (CryptoRNGT m)
Monad, Monad (CryptoRNGT m)
Monad (CryptoRNGT m)
-> (forall a. [Char] -> CryptoRNGT m a) -> MonadFail (CryptoRNGT m)
[Char] -> CryptoRNGT m a
forall a. [Char] -> CryptoRNGT m a
forall (m :: * -> *).
Monad m -> (forall a. [Char] -> m a) -> MonadFail m
forall (m :: * -> *). MonadFail m => Monad (CryptoRNGT m)
forall (m :: * -> *) a. MonadFail m => [Char] -> CryptoRNGT m a
fail :: [Char] -> CryptoRNGT m a
$cfail :: forall (m :: * -> *) a. MonadFail m => [Char] -> CryptoRNGT m a
$cp1MonadFail :: forall (m :: * -> *). MonadFail m => Monad (CryptoRNGT m)
MonadFail, Monad (CryptoRNGT m)
Alternative (CryptoRNGT m)
CryptoRNGT m a
Alternative (CryptoRNGT m)
-> Monad (CryptoRNGT m)
-> (forall a. CryptoRNGT m a)
-> (forall a. CryptoRNGT m a -> CryptoRNGT m a -> CryptoRNGT m a)
-> MonadPlus (CryptoRNGT m)
CryptoRNGT m a -> CryptoRNGT m a -> CryptoRNGT m a
forall a. CryptoRNGT m a
forall a. CryptoRNGT m a -> CryptoRNGT m a -> CryptoRNGT m a
forall (m :: * -> *).
Alternative m
-> Monad m
-> (forall a. m a)
-> (forall a. m a -> m a -> m a)
-> MonadPlus m
forall (m :: * -> *). MonadPlus m => Monad (CryptoRNGT m)
forall (m :: * -> *). MonadPlus m => Alternative (CryptoRNGT m)
forall (m :: * -> *) a. MonadPlus m => CryptoRNGT m a
forall (m :: * -> *) a.
MonadPlus m =>
CryptoRNGT m a -> CryptoRNGT m a -> CryptoRNGT m a
mplus :: CryptoRNGT m a -> CryptoRNGT m a -> CryptoRNGT m a
$cmplus :: forall (m :: * -> *) a.
MonadPlus m =>
CryptoRNGT m a -> CryptoRNGT m a -> CryptoRNGT m a
mzero :: CryptoRNGT m a
$cmzero :: forall (m :: * -> *) a. MonadPlus m => CryptoRNGT m a
$cp2MonadPlus :: forall (m :: * -> *). MonadPlus m => Monad (CryptoRNGT m)
$cp1MonadPlus :: forall (m :: * -> *). MonadPlus m => Alternative (CryptoRNGT m)
MonadPlus
           , MonadError e, Monad (CryptoRNGT m)
Monad (CryptoRNGT m)
-> (forall a. IO a -> CryptoRNGT m a) -> MonadIO (CryptoRNGT m)
IO a -> CryptoRNGT m a
forall a. IO a -> CryptoRNGT m a
forall (m :: * -> *).
Monad m -> (forall a. IO a -> m a) -> MonadIO m
forall (m :: * -> *). MonadIO m => Monad (CryptoRNGT m)
forall (m :: * -> *) a. MonadIO m => IO a -> CryptoRNGT m a
liftIO :: IO a -> CryptoRNGT m a
$cliftIO :: forall (m :: * -> *) a. MonadIO m => IO a -> CryptoRNGT m a
$cp1MonadIO :: forall (m :: * -> *). MonadIO m => Monad (CryptoRNGT m)
MonadIO,  MonadBase b, MonadBaseControl b
           , Monad (CryptoRNGT m)
e -> CryptoRNGT m a
Monad (CryptoRNGT m)
-> (forall e a. Exception e => e -> CryptoRNGT m a)
-> MonadThrow (CryptoRNGT m)
forall e a. Exception e => e -> CryptoRNGT m a
forall (m :: * -> *).
Monad m -> (forall e a. Exception e => e -> m a) -> MonadThrow m
forall (m :: * -> *). MonadThrow m => Monad (CryptoRNGT m)
forall (m :: * -> *) e a.
(MonadThrow m, Exception e) =>
e -> CryptoRNGT m a
throwM :: e -> CryptoRNGT m a
$cthrowM :: forall (m :: * -> *) e a.
(MonadThrow m, Exception e) =>
e -> CryptoRNGT m a
$cp1MonadThrow :: forall (m :: * -> *). MonadThrow m => Monad (CryptoRNGT m)
MonadThrow, MonadThrow (CryptoRNGT m)
MonadThrow (CryptoRNGT m)
-> (forall e a.
    Exception e =>
    CryptoRNGT m a -> (e -> CryptoRNGT m a) -> CryptoRNGT m a)
-> MonadCatch (CryptoRNGT m)
CryptoRNGT m a -> (e -> CryptoRNGT m a) -> CryptoRNGT m a
forall e a.
Exception e =>
CryptoRNGT m a -> (e -> CryptoRNGT m a) -> CryptoRNGT m a
forall (m :: * -> *).
MonadThrow m
-> (forall e a. Exception e => m a -> (e -> m a) -> m a)
-> MonadCatch m
forall (m :: * -> *). MonadCatch m => MonadThrow (CryptoRNGT m)
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
CryptoRNGT m a -> (e -> CryptoRNGT m a) -> CryptoRNGT m a
catch :: CryptoRNGT m a -> (e -> CryptoRNGT m a) -> CryptoRNGT m a
$ccatch :: forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
CryptoRNGT m a -> (e -> CryptoRNGT m a) -> CryptoRNGT m a
$cp1MonadCatch :: forall (m :: * -> *). MonadCatch m => MonadThrow (CryptoRNGT m)
MonadCatch, MonadCatch (CryptoRNGT m)
MonadCatch (CryptoRNGT m)
-> (forall b.
    ((forall a. CryptoRNGT m a -> CryptoRNGT m a) -> CryptoRNGT m b)
    -> CryptoRNGT m b)
-> (forall b.
    ((forall a. CryptoRNGT m a -> CryptoRNGT m a) -> CryptoRNGT m b)
    -> CryptoRNGT m b)
-> (forall a b c.
    CryptoRNGT m a
    -> (a -> ExitCase b -> CryptoRNGT m c)
    -> (a -> CryptoRNGT m b)
    -> CryptoRNGT m (b, c))
-> MonadMask (CryptoRNGT m)
CryptoRNGT m a
-> (a -> ExitCase b -> CryptoRNGT m c)
-> (a -> CryptoRNGT m b)
-> CryptoRNGT m (b, c)
((forall a. CryptoRNGT m a -> CryptoRNGT m a) -> CryptoRNGT m b)
-> CryptoRNGT m b
((forall a. CryptoRNGT m a -> CryptoRNGT m a) -> CryptoRNGT m b)
-> CryptoRNGT m b
forall b.
((forall a. CryptoRNGT m a -> CryptoRNGT m a) -> CryptoRNGT m b)
-> CryptoRNGT m b
forall a b c.
CryptoRNGT m a
-> (a -> ExitCase b -> CryptoRNGT m c)
-> (a -> CryptoRNGT m b)
-> CryptoRNGT m (b, c)
forall (m :: * -> *).
MonadCatch m
-> (forall b. ((forall a. m a -> m a) -> m b) -> m b)
-> (forall b. ((forall a. m a -> m a) -> m b) -> m b)
-> (forall a b c.
    m a -> (a -> ExitCase b -> m c) -> (a -> m b) -> m (b, c))
-> MonadMask m
forall (m :: * -> *). MonadMask m => MonadCatch (CryptoRNGT m)
forall (m :: * -> *) b.
MonadMask m =>
((forall a. CryptoRNGT m a -> CryptoRNGT m a) -> CryptoRNGT m b)
-> CryptoRNGT m b
forall (m :: * -> *) a b c.
MonadMask m =>
CryptoRNGT m a
-> (a -> ExitCase b -> CryptoRNGT m c)
-> (a -> CryptoRNGT m b)
-> CryptoRNGT m (b, c)
generalBracket :: CryptoRNGT m a
-> (a -> ExitCase b -> CryptoRNGT m c)
-> (a -> CryptoRNGT m b)
-> CryptoRNGT m (b, c)
$cgeneralBracket :: forall (m :: * -> *) a b c.
MonadMask m =>
CryptoRNGT m a
-> (a -> ExitCase b -> CryptoRNGT m c)
-> (a -> CryptoRNGT m b)
-> CryptoRNGT m (b, c)
uninterruptibleMask :: ((forall a. CryptoRNGT m a -> CryptoRNGT m a) -> CryptoRNGT m b)
-> CryptoRNGT m b
$cuninterruptibleMask :: forall (m :: * -> *) b.
MonadMask m =>
((forall a. CryptoRNGT m a -> CryptoRNGT m a) -> CryptoRNGT m b)
-> CryptoRNGT m b
mask :: ((forall a. CryptoRNGT m a -> CryptoRNGT m a) -> CryptoRNGT m b)
-> CryptoRNGT m b
$cmask :: forall (m :: * -> *) b.
MonadMask m =>
((forall a. CryptoRNGT m a -> CryptoRNGT m a) -> CryptoRNGT m b)
-> CryptoRNGT m b
$cp1MonadMask :: forall (m :: * -> *). MonadMask m => MonadCatch (CryptoRNGT m)
MonadMask
           , m a -> CryptoRNGT m a
(forall (m :: * -> *) a. Monad m => m a -> CryptoRNGT m a)
-> MonadTrans CryptoRNGT
forall (m :: * -> *) a. Monad m => m a -> CryptoRNGT m a
forall (t :: (* -> *) -> * -> *).
(forall (m :: * -> *) a. Monad m => m a -> t m a) -> MonadTrans t
lift :: m a -> CryptoRNGT m a
$clift :: forall (m :: * -> *) a. Monad m => m a -> CryptoRNGT m a
MonadTrans, MonadTrans CryptoRNGT
m (StT CryptoRNGT a) -> CryptoRNGT m a
MonadTrans CryptoRNGT
-> (forall (m :: * -> *) a.
    Monad m =>
    (Run CryptoRNGT -> m a) -> CryptoRNGT m a)
-> (forall (m :: * -> *) a.
    Monad m =>
    m (StT CryptoRNGT a) -> CryptoRNGT m a)
-> MonadTransControl CryptoRNGT
(Run CryptoRNGT -> m a) -> CryptoRNGT m a
forall (m :: * -> *) a.
Monad m =>
m (StT CryptoRNGT a) -> CryptoRNGT m a
forall (m :: * -> *) a.
Monad m =>
(Run CryptoRNGT -> m a) -> CryptoRNGT m a
forall (t :: (* -> *) -> * -> *).
MonadTrans t
-> (forall (m :: * -> *) a. Monad m => (Run t -> m a) -> t m a)
-> (forall (m :: * -> *) a. Monad m => m (StT t a) -> t m a)
-> MonadTransControl t
restoreT :: m (StT CryptoRNGT a) -> CryptoRNGT m a
$crestoreT :: forall (m :: * -> *) a.
Monad m =>
m (StT CryptoRNGT a) -> CryptoRNGT m a
liftWith :: (Run CryptoRNGT -> m a) -> CryptoRNGT m a
$cliftWith :: forall (m :: * -> *) a.
Monad m =>
(Run CryptoRNGT -> m a) -> CryptoRNGT m a
$cp1MonadTransControl :: MonadTrans CryptoRNGT
MonadTransControl
           )

mapCryptoRNGT :: (m a -> n b) -> CryptoRNGT m a -> CryptoRNGT n b
mapCryptoRNGT :: (m a -> n b) -> CryptoRNGT m a -> CryptoRNGT n b
mapCryptoRNGT m a -> n b
f CryptoRNGT m a
m = (CryptoRNGState -> n b) -> CryptoRNGT n b
forall (m :: * -> *) a. (CryptoRNGState -> m a) -> CryptoRNGT m a
withCryptoRNGState ((CryptoRNGState -> n b) -> CryptoRNGT n b)
-> (CryptoRNGState -> n b) -> CryptoRNGT n b
forall a b. (a -> b) -> a -> b
$ \CryptoRNGState
rng -> m a -> n b
f (CryptoRNGState -> CryptoRNGT m a -> m a
forall (m :: * -> *) a. CryptoRNGState -> CryptoRNGT m a -> m a
runCryptoRNGT CryptoRNGState
rng CryptoRNGT m a
m)

runCryptoRNGT :: CryptoRNGState -> CryptoRNGT m a -> m a
runCryptoRNGT :: CryptoRNGState -> CryptoRNGT m a -> m a
runCryptoRNGT CryptoRNGState
rng CryptoRNGT m a
m = ReaderT CryptoRNGState m a -> CryptoRNGState -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (CryptoRNGT m a -> ReaderT CryptoRNGState m a
forall (m :: * -> *) a.
CryptoRNGT m a -> ReaderT CryptoRNGState m a
unCryptoRNGT CryptoRNGT m a
m) CryptoRNGState
rng

withCryptoRNGState :: (CryptoRNGState -> m a) -> CryptoRNGT m a
withCryptoRNGState :: (CryptoRNGState -> m a) -> CryptoRNGT m a
withCryptoRNGState = ReaderT CryptoRNGState m a -> CryptoRNGT m a
forall (m :: * -> *) a.
ReaderT CryptoRNGState m a -> CryptoRNGT m a
CryptoRNGT (ReaderT CryptoRNGState m a -> CryptoRNGT m a)
-> ((CryptoRNGState -> m a) -> ReaderT CryptoRNGState m a)
-> (CryptoRNGState -> m a)
-> CryptoRNGT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CryptoRNGState -> m a) -> ReaderT CryptoRNGState m a
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT

instance MonadIO m => CryptoRNG (CryptoRNGT m) where
  randomBytes :: Int -> CryptoRNGT m ByteString
randomBytes Int
n  = ReaderT CryptoRNGState m CryptoRNGState
-> CryptoRNGT m CryptoRNGState
forall (m :: * -> *) a.
ReaderT CryptoRNGState m a -> CryptoRNGT m a
CryptoRNGT ReaderT CryptoRNGState m CryptoRNGState
forall r (m :: * -> *). MonadReader r m => m r
ask CryptoRNGT m CryptoRNGState
-> (CryptoRNGState -> CryptoRNGT m ByteString)
-> CryptoRNGT m ByteString
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= IO ByteString -> CryptoRNGT m ByteString
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ByteString -> CryptoRNGT m ByteString)
-> (CryptoRNGState -> IO ByteString)
-> CryptoRNGState
-> CryptoRNGT m ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> CryptoRNGState -> IO ByteString
randomBytesIO Int
n
  random :: CryptoRNGT m a
random         = ReaderT CryptoRNGState m CryptoRNGState
-> CryptoRNGT m CryptoRNGState
forall (m :: * -> *) a.
ReaderT CryptoRNGState m a -> CryptoRNGT m a
CryptoRNGT ReaderT CryptoRNGState m CryptoRNGState
forall r (m :: * -> *). MonadReader r m => m r
ask CryptoRNGT m CryptoRNGState
-> (CryptoRNGState -> CryptoRNGT m a) -> CryptoRNGT m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= IO a -> CryptoRNGT m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> CryptoRNGT m a)
-> (CryptoRNGState -> IO a) -> CryptoRNGState -> CryptoRNGT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CryptoRNGState -> IO a
forall a g (m :: * -> *). (Uniform a, StatefulGen g m) => g -> m a
R.uniformM
  randomR :: (a, a) -> CryptoRNGT m a
randomR (a, a)
bounds = ReaderT CryptoRNGState m CryptoRNGState
-> CryptoRNGT m CryptoRNGState
forall (m :: * -> *) a.
ReaderT CryptoRNGState m a -> CryptoRNGT m a
CryptoRNGT ReaderT CryptoRNGState m CryptoRNGState
forall r (m :: * -> *). MonadReader r m => m r
ask CryptoRNGT m CryptoRNGState
-> (CryptoRNGState -> CryptoRNGT m a) -> CryptoRNGT m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= IO a -> CryptoRNGT m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> CryptoRNGT m a)
-> (CryptoRNGState -> IO a) -> CryptoRNGState -> CryptoRNGT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a, a) -> CryptoRNGState -> IO a
forall a g (m :: * -> *).
(UniformRange a, StatefulGen g m) =>
(a, a) -> g -> m a
R.uniformRM (a, a)
bounds