module Cardano.Crypto.Signing.KeyGen
  ( keyGen,
    deterministicKeyGen,
  )
where

import Cardano.Crypto.Signing.SigningKey (SigningKey (..))
import Cardano.Crypto.Signing.VerificationKey (VerificationKey (..))
import qualified Cardano.Crypto.Wallet as CC
import Cardano.Prelude
import Crypto.Random (MonadRandom, getRandomBytes)
import Data.ByteArray (ScrubbedBytes)
import qualified Data.ByteString as BS

-- TODO: this is just a placeholder for actual (not ready yet) derivation
-- of keypair from seed in cardano-crypto API
createKeypairFromSeed :: BS.ByteString -> (CC.XPub, CC.XPrv)
createKeypairFromSeed :: ByteString -> (XPub, XPrv)
createKeypairFromSeed ByteString
seed =
  let prv :: XPrv
prv = ByteString -> ScrubbedBytes -> XPrv
forall passPhrase seed.
(ByteArrayAccess passPhrase, ByteArrayAccess seed) =>
seed -> passPhrase -> XPrv
CC.generate ByteString
seed (ScrubbedBytes
forall a. Monoid a => a
mempty :: ScrubbedBytes) in (HasCallStack => XPrv -> XPub
XPrv -> XPub
CC.toXPub XPrv
prv, XPrv
prv)

-- | 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.
keyGen :: MonadRandom m => m (VerificationKey, SigningKey)
keyGen :: m (VerificationKey, SigningKey)
keyGen = do
  ByteString
seed <- Int -> m ByteString
forall (m :: * -> *) byteArray.
(MonadRandom m, ByteArray byteArray) =>
Int -> m byteArray
getRandomBytes Int
32
  let (XPub
vk, XPrv
sk) = ByteString -> (XPub, XPrv)
createKeypairFromSeed ByteString
seed
  (VerificationKey, SigningKey) -> m (VerificationKey, SigningKey)
forall (m :: * -> *) a. Monad m => a -> m a
return (XPub -> VerificationKey
VerificationKey XPub
vk, XPrv -> SigningKey
SigningKey XPrv
sk)

-- | Create key pair deterministically from 32 bytes.
deterministicKeyGen :: BS.ByteString -> (VerificationKey, SigningKey)
deterministicKeyGen :: ByteString -> (VerificationKey, SigningKey)
deterministicKeyGen ByteString
seed =
  (XPub -> VerificationKey)
-> (XPrv -> SigningKey)
-> (XPub, XPrv)
-> (VerificationKey, SigningKey)
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap XPub -> VerificationKey
VerificationKey XPrv -> SigningKey
SigningKey (ByteString -> (XPub, XPrv)
createKeypairFromSeed ByteString
seed)