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 :: m (RedeemVerificationKey, RedeemSigningKey)
redeemKeyGen = do
  SecretKey
sk <- m SecretKey
forall (m :: * -> *). MonadRandom m => m SecretKey
Ed25519.generateSecretKey
  (RedeemVerificationKey, RedeemSigningKey)
-> m (RedeemVerificationKey, RedeemSigningKey)
forall (m :: * -> *) a. Monad m => a -> m a
return (PublicKey -> RedeemVerificationKey
RedeemVerificationKey (PublicKey -> RedeemVerificationKey)
-> PublicKey -> 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 CryptoFailable SecretKey -> Maybe SecretKey
forall a. CryptoFailable a -> Maybe a
maybeCryptoError (CryptoFailable SecretKey -> Maybe SecretKey)
-> CryptoFailable SecretKey -> Maybe SecretKey
forall a b. (a -> b) -> a -> b
$ Bytes -> CryptoFailable SecretKey
forall ba. ByteArrayAccess ba => ba -> CryptoFailable SecretKey
Ed25519.secretKey (ByteString -> Bytes
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
BA.convert ByteString
seed :: BA.Bytes) of
    Just SecretKey
r -> (RedeemVerificationKey, RedeemSigningKey)
-> Maybe (RedeemVerificationKey, RedeemSigningKey)
forall a. a -> Maybe a
Just (PublicKey -> RedeemVerificationKey
RedeemVerificationKey (PublicKey -> RedeemVerificationKey)
-> PublicKey -> RedeemVerificationKey
forall a b. (a -> b) -> a -> b
$ SecretKey -> PublicKey
Ed25519.toPublic SecretKey
r, SecretKey -> RedeemSigningKey
RedeemSigningKey SecretKey
r)
    Maybe SecretKey
Nothing ->
      String -> Maybe (RedeemVerificationKey, RedeemSigningKey)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Cardano.Crypto.Signing.Redeem.hs redeemDeterministicKeyGen failed"