-- SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later

{-# OPTIONS_GHC -fno-warn-orphans #-}

module Crypto.Random.Instances
  (
  ) where

import ClassyPrelude

import Crypto.Random
import System.Random (RandomGen(..))
import qualified Crypto.Error as Crypto

import qualified Data.ByteArray as BA

import Data.Bits

import Data.Binary (Binary)
import qualified Data.Binary as Binary

import Control.Monad.Fail (MonadFail(..))

import qualified Data.ByteString as BS


instance RandomGen ChaChaDRG where
  genWord64 g = withRandomBytes g (finiteBitSize (maxBound :: Word64) `div` 8) (foldr (\x acc -> acc `shiftL` 8 .|. fromIntegral x) zeroBits . BA.unpack @BA.Bytes)
  genWord32 g = withRandomBytes g (finiteBitSize (maxBound :: Word32) `div` 8) (foldr (\x acc -> acc `shiftL` 8 .|. fromIntegral x) zeroBits . BA.unpack @BA.Bytes)
  split g = withDRG g drgNew

instance Binary Seed where
  put = mapM_ Binary.putWord8 . (BA.convert :: Seed -> ByteString)
  get = do
    seedBytes <- BS.pack <$> replicateM 40 Binary.getWord8
    Crypto.onCryptoFailure (fail . show) return $ seedFromBinary seedBytes
