{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Crypto.Random.ChaChaDRG
( ChaChaDRG
, initialize
, initializeWords
) where
import Crypto.Random.Types
import Crypto.Internal.Imports
import Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess, ScrubbedBytes)
import qualified Crypto.Internal.ByteArray as B
import Foreign.Storable (pokeElemOff)
import qualified Crypto.Cipher.ChaCha as C
instance DRG ChaChaDRG where
randomBytesGenerate = generate
newtype ChaChaDRG = ChaChaDRG C.StateSimple
deriving (NFData)
initialize :: ByteArrayAccess seed
=> seed
-> ChaChaDRG
initialize seed = ChaChaDRG $ C.initializeSimple seed
initializeWords :: (Word64, Word64, Word64, Word64, Word64) -> ChaChaDRG
initializeWords (a,b,c,d,e) = initialize (B.allocAndFreeze 40 fill :: ScrubbedBytes)
where fill s = mapM_ (uncurry (pokeElemOff s)) [(0,a), (1,b), (2,c), (3,d), (4,e)]
generate :: ByteArray output => Int -> ChaChaDRG -> (output, ChaChaDRG)
generate nbBytes st@(ChaChaDRG prevSt)
| nbBytes <= 0 = (B.empty, st)
| otherwise = let (output, newSt) = C.generateSimple prevSt nbBytes in (output, ChaChaDRG newSt)