content: {-# LANGUAGE FlexibleContexts #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE TypeFamilies #-}
  
  -- DUPLICATE -- adapted from: cardano-api/src/Cardano/Api/Key.hs
  
  module Cardano.Api.Key
    ( AsType (AsVerificationKey, AsSigningKey)
    , CastSigningKeyRole (..)
    , CastVerificationKeyRole (..)
    , Key (..)
    ) where
  
  import Cardano.Api.Any
  import Cardano.Api.SerialiseTextEnvelope
  import qualified Cardano.Crypto.DSIGN.Class as Crypto
  import qualified Cardano.Crypto.Seed as Crypto
  import Data.Kind (Type)
  
  -- | An interface for cryptographic keys used for signatures with a 'SigningKey'
  -- and a 'VerificationKey' key.
  --
  -- This interface does not provide actual signing or verifying functions since
  -- this API is concerned with the management of keys: generating and
  -- serialising.
  class
    ( Eq (VerificationKey keyrole)
    , Show (VerificationKey keyrole)
    , SerialiseAsRawBytes (Hash keyrole)
    , HasTextEnvelope (VerificationKey keyrole)
    , HasTextEnvelope (SigningKey keyrole)
    ) =>
    Key keyrole
    where
    -- | The type of cryptographic verification key, for each key role.
    data VerificationKey keyrole :: Type
  
    -- | The type of cryptographic signing key, for each key role.
    data SigningKey keyrole :: Type
  
    -- | Get the corresponding verification key from a signing key.
    getVerificationKey :: SigningKey keyrole -> VerificationKey keyrole
  
    -- | Generate a 'SigningKey' deterministically, given a 'Crypto.Seed'. The
    -- required size of the seed is given by 'deterministicSigningKeySeedSize'.
    deterministicSigningKey :: AsType keyrole -> Crypto.Seed -> SigningKey keyrole
  
    deterministicSigningKeySeedSize :: AsType keyrole -> Word
  
    verificationKeyHash :: VerificationKey keyrole -> Hash keyrole
  
    -- | Generate a 'SigningKey' using a seed from operating system entropy.
    generateSigningKey :: AsType keyrole -> IO (SigningKey keyrole)
    generateSigningKey keytype = do
      --
      -- For KES we can override this to keep the seed and key in mlocked memory
      -- at all times.
      --
      seed <- Crypto.readSeedFromSystemEntropy seedSize
      return $! deterministicSigningKey keytype seed
     where
      seedSize = deterministicSigningKeySeedSize keytype
  
  instance HasTypeProxy a => HasTypeProxy (VerificationKey a) where
    data AsType (VerificationKey a) = AsVerificationKey (AsType a)
    proxyToAsType _ = AsVerificationKey (proxyToAsType (Proxy :: Proxy a))
  
  instance HasTypeProxy a => HasTypeProxy (SigningKey a) where
    data AsType (SigningKey a) = AsSigningKey (AsType a)
    proxyToAsType _ = AsSigningKey (proxyToAsType (Proxy :: Proxy a))
  
  -- | Some key roles share the same representation and it is sometimes
  -- legitimate to change the role of a key.
  class CastVerificationKeyRole keyroleA keyroleB where
    -- | Change the role of a 'VerificationKey', if the representation permits.
    castVerificationKey :: VerificationKey keyroleA -> VerificationKey keyroleB
  
  class CastSigningKeyRole keyroleA keyroleB where
    -- | Change the role of a 'SigningKey', if the representation permits.
    castSigningKey :: SigningKey keyroleA -> SigningKey keyroleB
  