module Cardano.Crypto.Signing.Redeem.KeyGen (
  redeemKeyGen,
  redeemDeterministicKeyGen,
)
where

import Cardano.Crypto.Signing.Redeem.SigningKey (RedeemSigningKey (..))
import Cardano.Crypto.Signing.Redeem.VerificationKey (RedeemVerificationKey (..))
import Cardano.Prelude
import Control.Monad (fail)
import Crypto.Error (maybeCryptoError)
import qualified Crypto.PubKey.Ed25519 as Ed25519
import Crypto.Random (MonadRandom)
import qualified Data.ByteArray as BA
import qualified Data.ByteString as BS

-- | Generate a key pair. It's recommended to run it with 'runSecureRandom' from
--   "Cardano.Crypto.Random" because the OpenSSL generator is probably safer
--   than the default IO generator.
redeemKeyGen :: MonadRandom m => m (RedeemVerificationKey, RedeemSigningKey)
redeemKeyGen :: forall (m :: * -> *).
MonadRandom m =>
m (RedeemVerificationKey, RedeemSigningKey)
redeemKeyGen = do
  SecretKey
sk <- forall (m :: * -> *). MonadRandom m => m SecretKey
Ed25519.generateSecretKey
  forall (m :: * -> *) a. Monad m => a -> m a
return (PublicKey -> RedeemVerificationKey
RedeemVerificationKey forall a b. (a -> b) -> a -> b
$ SecretKey -> PublicKey
Ed25519.toPublic SecretKey
sk, SecretKey -> RedeemSigningKey
RedeemSigningKey SecretKey
sk)

-- | Create key pair deterministically from 32 bytes
redeemDeterministicKeyGen ::
  BS.ByteString -> Maybe (RedeemVerificationKey, RedeemSigningKey)
redeemDeterministicKeyGen :: ByteString -> Maybe (RedeemVerificationKey, RedeemSigningKey)
redeemDeterministicKeyGen ByteString
seed =
  case forall a. CryptoFailable a -> Maybe a
maybeCryptoError forall a b. (a -> b) -> a -> b
$ forall ba. ByteArrayAccess ba => ba -> CryptoFailable SecretKey
Ed25519.secretKey (forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
BA.convert ByteString
seed :: BA.Bytes) of
    Just SecretKey
r -> forall a. a -> Maybe a
Just (PublicKey -> RedeemVerificationKey
RedeemVerificationKey forall a b. (a -> b) -> a -> b
$ SecretKey -> PublicKey
Ed25519.toPublic SecretKey
r, SecretKey -> RedeemSigningKey
RedeemSigningKey SecretKey
r)
    Maybe SecretKey
Nothing ->
      forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Cardano.Crypto.Signing.Redeem.hs redeemDeterministicKeyGen failed"