-- SPDX-FileCopyrightText: 2021 Oxhead Alpha
-- SPDX-License-Identifier: LicenseRef-MIT-OA

module Hedgehog.Gen.Tezos.Crypto.P256
  ( genPublicKey
  , genSecretKey
  , genSignature
  ) where

import Crypto.Random (drgNewSeed, seedFromInteger, withDRG)
import Hedgehog (MonadGen)
import Hedgehog.Gen qualified as Gen
import Hedgehog.Range qualified as Range

import Morley.Tezos.Crypto.P256
  (PublicKey, SecretKey, Signature, detSecretKey, detSecretKeyDo, sign, toPublic)

genPublicKey :: MonadGen m => m PublicKey
genPublicKey :: forall (m :: * -> *). MonadGen m => m PublicKey
genPublicKey = SecretKey -> PublicKey
toPublic (SecretKey -> PublicKey) -> m SecretKey -> m PublicKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m SecretKey
forall (m :: * -> *). MonadGen m => m SecretKey
genSecretKey

genSecretKey :: MonadGen m => m SecretKey
genSecretKey :: forall (m :: * -> *). MonadGen m => m SecretKey
genSecretKey = ByteString -> SecretKey
detSecretKey (ByteString -> SecretKey) -> m ByteString -> m SecretKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Range Int -> m ByteString
forall (m :: * -> *). MonadGen m => Range Int -> m ByteString
Gen.bytes (Int -> Range Int
forall a. a -> Range a
Range.singleton Int
32)

genSignature :: MonadGen m => m Signature
genSignature :: forall (m :: * -> *). MonadGen m => m Signature
genSignature = do
  ChaChaDRG
seed <- Seed -> ChaChaDRG
drgNewSeed (Seed -> ChaChaDRG) -> (Integer -> Seed) -> Integer -> ChaChaDRG
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Seed
seedFromInteger (Integer -> ChaChaDRG) -> m Integer -> m ChaChaDRG
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Range Integer -> m Integer
forall (m :: * -> *) a. (MonadGen m, Integral a) => Range a -> m a
Gen.integral (Integer -> Integer -> Integer -> Range Integer
forall a. Integral a => a -> a -> a -> Range a
Range.linearFrom Integer
0 Integer
-1000 Integer
1000)
  Word8
byteToSign <- Range Word8 -> m Word8
forall (m :: * -> *). MonadGen m => Range Word8 -> m Word8
Gen.word8 Range Word8
forall a. (Bounded a, Integral a) => Range a
Range.linearBounded
  return $ (Signature, ChaChaDRG) -> Signature
forall a b. (a, b) -> a
fst ((Signature, ChaChaDRG) -> Signature)
-> (Signature, ChaChaDRG) -> Signature
forall a b. (a -> b) -> a -> b
$ ChaChaDRG
-> MonadPseudoRandom ChaChaDRG Signature -> (Signature, ChaChaDRG)
forall gen a. DRG gen => gen -> MonadPseudoRandom gen a -> (a, gen)
withDRG ChaChaDRG
seed (MonadPseudoRandom ChaChaDRG Signature -> (Signature, ChaChaDRG))
-> MonadPseudoRandom ChaChaDRG Signature -> (Signature, ChaChaDRG)
forall a b. (a -> b) -> a -> b
$ do
    SecretKey
sk <- MonadPseudoRandom ChaChaDRG SecretKey
forall (m :: * -> *). MonadRandom m => m SecretKey
detSecretKeyDo
    SecretKey -> ByteString -> MonadPseudoRandom ChaChaDRG Signature
forall (m :: * -> *).
MonadRandom m =>
SecretKey -> ByteString -> m Signature
sign SecretKey
sk (OneItem ByteString -> ByteString
forall x. One x => OneItem x -> x
one Word8
OneItem ByteString
byteToSign)