{-# LANGUAGE GeneralisedNewtypeDeriving #-}

module Cardano.CLI.Byron.Key
  ( -- * Keys
    ByronKeyFailure(..)
  , NewSigningKeyFile(..)
  , NewVerificationKeyFile(..)
  , VerificationKeyFile(..)
  , CardanoEra(..)
  , serialiseSigningKey
  , deserialiseSigningKey
  , keygen
  , prettyPublicKey
  , readEraSigningKey
  , readPaymentVerificationKey
  , renderByronKeyFailure
  , serialisePoorKey
    -- * Passwords
  , PasswordRequirement(..)
  , PasswordPrompt
  , getPassphrase
  )
where

import           Cardano.Prelude hiding (option, show, trace, (%))
import           Prelude (String, show)

import           Codec.CBOR.Read (DeserialiseFailure, deserialiseFromBytes)
import           Codec.CBOR.Write (toLazyByteString)

import           Control.Monad.Trans.Except.Extra (firstExceptT, handleIOExceptT, hoistEither)
import qualified Data.ByteArray as BA
import qualified Data.ByteString as SB
import qualified Data.ByteString.Lazy as LB
import qualified Data.ByteString.UTF8 as UTF8
import           Data.String (fromString)
import qualified Data.Text as T
import           Formatting (build, sformat, (%))

import           System.IO (hFlush, hSetEcho)

import qualified Cardano.Chain.Common as Common
import qualified Cardano.Chain.Genesis as Genesis
import qualified Cardano.CLI.Byron.Legacy as Legacy
import           Cardano.CLI.Helpers (textShow)
import           Cardano.CLI.Types
import           Cardano.Crypto (SigningKey (..))
import qualified Cardano.Crypto.Random as Crypto
import qualified Cardano.Crypto.Signing as Crypto


data ByronKeyFailure
  = ReadSigningKeyFailure !FilePath !Text
  | ReadVerificationKeyFailure !FilePath !Text
  | SigningKeyDeserialisationFailed !FilePath !DeserialiseFailure
  | VerificationKeyDeserialisationFailed !FilePath !Text
  deriving Int -> ByronKeyFailure -> ShowS
[ByronKeyFailure] -> ShowS
ByronKeyFailure -> String
(Int -> ByronKeyFailure -> ShowS)
-> (ByronKeyFailure -> String)
-> ([ByronKeyFailure] -> ShowS)
-> Show ByronKeyFailure
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ByronKeyFailure] -> ShowS
$cshowList :: [ByronKeyFailure] -> ShowS
show :: ByronKeyFailure -> String
$cshow :: ByronKeyFailure -> String
showsPrec :: Int -> ByronKeyFailure -> ShowS
$cshowsPrec :: Int -> ByronKeyFailure -> ShowS
Show

renderByronKeyFailure :: ByronKeyFailure -> Text
renderByronKeyFailure :: ByronKeyFailure -> Text
renderByronKeyFailure ByronKeyFailure
err =
  case ByronKeyFailure
err of
    ReadSigningKeyFailure String
sKeyFp Text
readErr ->
      Text
"Error reading signing key at: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. Show a => a -> Text
textShow String
sKeyFp Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" Error: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
forall a. Show a => a -> Text
textShow Text
readErr
    ReadVerificationKeyFailure String
vKeyFp Text
readErr ->
      Text
"Error reading verification key at: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. Show a => a -> Text
textShow String
vKeyFp Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" Error: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
forall a. Show a => a -> Text
textShow Text
readErr
    SigningKeyDeserialisationFailed String
sKeyFp DeserialiseFailure
deSerError ->
      Text
"Error derserializing signing key at: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. Show a => a -> Text
textShow String
sKeyFp Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" Error: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> DeserialiseFailure -> Text
forall a. Show a => a -> Text
textShow DeserialiseFailure
deSerError
    VerificationKeyDeserialisationFailed String
vKeyFp Text
deSerError ->
      Text
"Error derserializing verification key at: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. Show a => a -> Text
textShow String
vKeyFp Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" Error: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
forall a. Show a => a -> Text
textShow Text
deSerError

newtype NewSigningKeyFile =
  NewSigningKeyFile FilePath
  deriving (NewSigningKeyFile -> NewSigningKeyFile -> Bool
(NewSigningKeyFile -> NewSigningKeyFile -> Bool)
-> (NewSigningKeyFile -> NewSigningKeyFile -> Bool)
-> Eq NewSigningKeyFile
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NewSigningKeyFile -> NewSigningKeyFile -> Bool
$c/= :: NewSigningKeyFile -> NewSigningKeyFile -> Bool
== :: NewSigningKeyFile -> NewSigningKeyFile -> Bool
$c== :: NewSigningKeyFile -> NewSigningKeyFile -> Bool
Eq, Eq NewSigningKeyFile
Eq NewSigningKeyFile
-> (NewSigningKeyFile -> NewSigningKeyFile -> Ordering)
-> (NewSigningKeyFile -> NewSigningKeyFile -> Bool)
-> (NewSigningKeyFile -> NewSigningKeyFile -> Bool)
-> (NewSigningKeyFile -> NewSigningKeyFile -> Bool)
-> (NewSigningKeyFile -> NewSigningKeyFile -> Bool)
-> (NewSigningKeyFile -> NewSigningKeyFile -> NewSigningKeyFile)
-> (NewSigningKeyFile -> NewSigningKeyFile -> NewSigningKeyFile)
-> Ord NewSigningKeyFile
NewSigningKeyFile -> NewSigningKeyFile -> Bool
NewSigningKeyFile -> NewSigningKeyFile -> Ordering
NewSigningKeyFile -> NewSigningKeyFile -> NewSigningKeyFile
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: NewSigningKeyFile -> NewSigningKeyFile -> NewSigningKeyFile
$cmin :: NewSigningKeyFile -> NewSigningKeyFile -> NewSigningKeyFile
max :: NewSigningKeyFile -> NewSigningKeyFile -> NewSigningKeyFile
$cmax :: NewSigningKeyFile -> NewSigningKeyFile -> NewSigningKeyFile
>= :: NewSigningKeyFile -> NewSigningKeyFile -> Bool
$c>= :: NewSigningKeyFile -> NewSigningKeyFile -> Bool
> :: NewSigningKeyFile -> NewSigningKeyFile -> Bool
$c> :: NewSigningKeyFile -> NewSigningKeyFile -> Bool
<= :: NewSigningKeyFile -> NewSigningKeyFile -> Bool
$c<= :: NewSigningKeyFile -> NewSigningKeyFile -> Bool
< :: NewSigningKeyFile -> NewSigningKeyFile -> Bool
$c< :: NewSigningKeyFile -> NewSigningKeyFile -> Bool
compare :: NewSigningKeyFile -> NewSigningKeyFile -> Ordering
$ccompare :: NewSigningKeyFile -> NewSigningKeyFile -> Ordering
$cp1Ord :: Eq NewSigningKeyFile
Ord, Int -> NewSigningKeyFile -> ShowS
[NewSigningKeyFile] -> ShowS
NewSigningKeyFile -> String
(Int -> NewSigningKeyFile -> ShowS)
-> (NewSigningKeyFile -> String)
-> ([NewSigningKeyFile] -> ShowS)
-> Show NewSigningKeyFile
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NewSigningKeyFile] -> ShowS
$cshowList :: [NewSigningKeyFile] -> ShowS
show :: NewSigningKeyFile -> String
$cshow :: NewSigningKeyFile -> String
showsPrec :: Int -> NewSigningKeyFile -> ShowS
$cshowsPrec :: Int -> NewSigningKeyFile -> ShowS
Show, String -> NewSigningKeyFile
(String -> NewSigningKeyFile) -> IsString NewSigningKeyFile
forall a. (String -> a) -> IsString a
fromString :: String -> NewSigningKeyFile
$cfromString :: String -> NewSigningKeyFile
IsString)

newtype NewVerificationKeyFile =
  NewVerificationKeyFile FilePath
   deriving (NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
(NewVerificationKeyFile -> NewVerificationKeyFile -> Bool)
-> (NewVerificationKeyFile -> NewVerificationKeyFile -> Bool)
-> Eq NewVerificationKeyFile
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
$c/= :: NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
== :: NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
$c== :: NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
Eq, Eq NewVerificationKeyFile
Eq NewVerificationKeyFile
-> (NewVerificationKeyFile -> NewVerificationKeyFile -> Ordering)
-> (NewVerificationKeyFile -> NewVerificationKeyFile -> Bool)
-> (NewVerificationKeyFile -> NewVerificationKeyFile -> Bool)
-> (NewVerificationKeyFile -> NewVerificationKeyFile -> Bool)
-> (NewVerificationKeyFile -> NewVerificationKeyFile -> Bool)
-> (NewVerificationKeyFile
    -> NewVerificationKeyFile -> NewVerificationKeyFile)
-> (NewVerificationKeyFile
    -> NewVerificationKeyFile -> NewVerificationKeyFile)
-> Ord NewVerificationKeyFile
NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
NewVerificationKeyFile -> NewVerificationKeyFile -> Ordering
NewVerificationKeyFile
-> NewVerificationKeyFile -> NewVerificationKeyFile
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: NewVerificationKeyFile
-> NewVerificationKeyFile -> NewVerificationKeyFile
$cmin :: NewVerificationKeyFile
-> NewVerificationKeyFile -> NewVerificationKeyFile
max :: NewVerificationKeyFile
-> NewVerificationKeyFile -> NewVerificationKeyFile
$cmax :: NewVerificationKeyFile
-> NewVerificationKeyFile -> NewVerificationKeyFile
>= :: NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
$c>= :: NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
> :: NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
$c> :: NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
<= :: NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
$c<= :: NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
< :: NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
$c< :: NewVerificationKeyFile -> NewVerificationKeyFile -> Bool
compare :: NewVerificationKeyFile -> NewVerificationKeyFile -> Ordering
$ccompare :: NewVerificationKeyFile -> NewVerificationKeyFile -> Ordering
$cp1Ord :: Eq NewVerificationKeyFile
Ord, Int -> NewVerificationKeyFile -> ShowS
[NewVerificationKeyFile] -> ShowS
NewVerificationKeyFile -> String
(Int -> NewVerificationKeyFile -> ShowS)
-> (NewVerificationKeyFile -> String)
-> ([NewVerificationKeyFile] -> ShowS)
-> Show NewVerificationKeyFile
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NewVerificationKeyFile] -> ShowS
$cshowList :: [NewVerificationKeyFile] -> ShowS
show :: NewVerificationKeyFile -> String
$cshow :: NewVerificationKeyFile -> String
showsPrec :: Int -> NewVerificationKeyFile -> ShowS
$cshowsPrec :: Int -> NewVerificationKeyFile -> ShowS
Show, String -> NewVerificationKeyFile
(String -> NewVerificationKeyFile)
-> IsString NewVerificationKeyFile
forall a. (String -> a) -> IsString a
fromString :: String -> NewVerificationKeyFile
$cfromString :: String -> NewVerificationKeyFile
IsString)

-- | Whether to require a password, or to supply an empty one.
data PasswordRequirement
  =  GetPassword
  |  EmptyPassword
  deriving (PasswordRequirement -> PasswordRequirement -> Bool
(PasswordRequirement -> PasswordRequirement -> Bool)
-> (PasswordRequirement -> PasswordRequirement -> Bool)
-> Eq PasswordRequirement
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PasswordRequirement -> PasswordRequirement -> Bool
$c/= :: PasswordRequirement -> PasswordRequirement -> Bool
== :: PasswordRequirement -> PasswordRequirement -> Bool
$c== :: PasswordRequirement -> PasswordRequirement -> Bool
Eq, Int -> PasswordRequirement -> ShowS
[PasswordRequirement] -> ShowS
PasswordRequirement -> String
(Int -> PasswordRequirement -> ShowS)
-> (PasswordRequirement -> String)
-> ([PasswordRequirement] -> ShowS)
-> Show PasswordRequirement
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PasswordRequirement] -> ShowS
$cshowList :: [PasswordRequirement] -> ShowS
show :: PasswordRequirement -> String
$cshow :: PasswordRequirement -> String
showsPrec :: Int -> PasswordRequirement -> ShowS
$cshowsPrec :: Int -> PasswordRequirement -> ShowS
Show)

type PasswordPrompt = String

-- | Some commands have variants or file formats that depend on the era.
--
-- TODO: this looks like it's only used for Byron era keys, so could be renamed
--
data CardanoEra = ByronEraLegacy | ByronEra
  deriving Int -> CardanoEra -> ShowS
[CardanoEra] -> ShowS
CardanoEra -> String
(Int -> CardanoEra -> ShowS)
-> (CardanoEra -> String)
-> ([CardanoEra] -> ShowS)
-> Show CardanoEra
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CardanoEra] -> ShowS
$cshowList :: [CardanoEra] -> ShowS
show :: CardanoEra -> String
$cshow :: CardanoEra -> String
showsPrec :: Int -> CardanoEra -> ShowS
$cshowsPrec :: Int -> CardanoEra -> ShowS
Show

serialiseSigningKey
  :: CardanoEra
  -> Crypto.SigningKey
  -> Either ByronKeyFailure LB.ByteString
serialiseSigningKey :: CardanoEra -> SigningKey -> Either ByronKeyFailure ByteString
serialiseSigningKey CardanoEra
ByronEraLegacy (Crypto.SigningKey XPrv
k) = ByteString -> Either ByronKeyFailure ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Either ByronKeyFailure ByteString)
-> ByteString -> Either ByronKeyFailure ByteString
forall a b. (a -> b) -> a -> b
$ Encoding -> ByteString
toLazyByteString (XPrv -> Encoding
Crypto.toCBORXPrv XPrv
k)
serialiseSigningKey CardanoEra
ByronEra (Crypto.SigningKey XPrv
k) = ByteString -> Either ByronKeyFailure ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Either ByronKeyFailure ByteString)
-> ByteString -> Either ByronKeyFailure ByteString
forall a b. (a -> b) -> a -> b
$ Encoding -> ByteString
toLazyByteString (XPrv -> Encoding
Crypto.toCBORXPrv XPrv
k)

deserialiseSigningKey :: CardanoEra -> FilePath -> LB.ByteString
                      -> Either ByronKeyFailure SigningKey
deserialiseSigningKey :: CardanoEra
-> String -> ByteString -> Either ByronKeyFailure SigningKey
deserialiseSigningKey CardanoEra
ByronEraLegacy String
fp ByteString
delSkey =
  case (forall s. Decoder s LegacyDelegateKey)
-> ByteString
-> Either DeserialiseFailure (ByteString, LegacyDelegateKey)
forall a.
(forall s. Decoder s a)
-> ByteString -> Either DeserialiseFailure (ByteString, a)
deserialiseFromBytes forall s. Decoder s LegacyDelegateKey
Legacy.decodeLegacyDelegateKey ByteString
delSkey of
    Left DeserialiseFailure
deSerFail -> ByronKeyFailure -> Either ByronKeyFailure SigningKey
forall a b. a -> Either a b
Left (ByronKeyFailure -> Either ByronKeyFailure SigningKey)
-> ByronKeyFailure -> Either ByronKeyFailure SigningKey
forall a b. (a -> b) -> a -> b
$ String -> DeserialiseFailure -> ByronKeyFailure
SigningKeyDeserialisationFailed String
fp DeserialiseFailure
deSerFail
    Right (ByteString
_, Legacy.LegacyDelegateKey SigningKey
sKey ) -> SigningKey -> Either ByronKeyFailure SigningKey
forall (f :: * -> *) a. Applicative f => a -> f a
pure SigningKey
sKey

deserialiseSigningKey CardanoEra
ByronEra String
fp ByteString
delSkey =
  case (forall s. Decoder s XPrv)
-> ByteString -> Either DeserialiseFailure (ByteString, XPrv)
forall a.
(forall s. Decoder s a)
-> ByteString -> Either DeserialiseFailure (ByteString, a)
deserialiseFromBytes forall s. Decoder s XPrv
Crypto.fromCBORXPrv ByteString
delSkey of
    Left DeserialiseFailure
deSerFail -> ByronKeyFailure -> Either ByronKeyFailure SigningKey
forall a b. a -> Either a b
Left (ByronKeyFailure -> Either ByronKeyFailure SigningKey)
-> ByronKeyFailure -> Either ByronKeyFailure SigningKey
forall a b. (a -> b) -> a -> b
$ String -> DeserialiseFailure -> ByronKeyFailure
SigningKeyDeserialisationFailed String
fp DeserialiseFailure
deSerFail
    Right (ByteString
_, XPrv
sKey) -> SigningKey -> Either ByronKeyFailure SigningKey
forall a b. b -> Either a b
Right (SigningKey -> Either ByronKeyFailure SigningKey)
-> SigningKey -> Either ByronKeyFailure SigningKey
forall a b. (a -> b) -> a -> b
$ XPrv -> SigningKey
SigningKey XPrv
sKey


-- | Print some invariant properties of a public key:
--   its hash and formatted view.
prettyPublicKey :: Crypto.VerificationKey -> Text
prettyPublicKey :: VerificationKey -> Text
prettyPublicKey VerificationKey
vk =
  Format
  Text
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
-> AddressHash VerificationKey
-> VerificationKey
-> VerificationKey
-> Text
forall a. Format Text a -> a
sformat (  Format
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
"    public key hash: "Format
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
-> Format
     Text
     (AddressHash VerificationKey
      -> VerificationKey -> VerificationKey -> Text)
-> Format
     Text
     (AddressHash VerificationKey
      -> VerificationKey -> VerificationKey -> Text)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format
  (VerificationKey -> VerificationKey -> Text)
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
forall a r. Buildable a => Format r (a -> r)
build Format
  (VerificationKey -> VerificationKey -> Text)
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
-> Format Text (VerificationKey -> VerificationKey -> Text)
-> Format
     Text
     (AddressHash VerificationKey
      -> VerificationKey -> VerificationKey -> Text)
forall r a r'. Format r a -> Format r' r -> Format r' a
%
           Format
  (VerificationKey -> VerificationKey -> Text)
  (VerificationKey -> VerificationKey -> Text)
"\npublic key (base64): "Format
  (VerificationKey -> VerificationKey -> Text)
  (VerificationKey -> VerificationKey -> Text)
-> Format Text (VerificationKey -> VerificationKey -> Text)
-> Format Text (VerificationKey -> VerificationKey -> Text)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format
  (VerificationKey -> Text)
  (VerificationKey -> VerificationKey -> Text)
forall r. Format r (VerificationKey -> r)
Crypto.fullVerificationKeyF Format
  (VerificationKey -> Text)
  (VerificationKey -> VerificationKey -> Text)
-> Format Text (VerificationKey -> Text)
-> Format Text (VerificationKey -> VerificationKey -> Text)
forall r a r'. Format r a -> Format r' r -> Format r' a
%
           Format (VerificationKey -> Text) (VerificationKey -> Text)
"\n   public key (hex): "Format (VerificationKey -> Text) (VerificationKey -> Text)
-> Format Text (VerificationKey -> Text)
-> Format Text (VerificationKey -> Text)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format Text (VerificationKey -> Text)
forall r. Format r (VerificationKey -> r)
Crypto.fullVerificationKeyHexF)
    (VerificationKey -> AddressHash VerificationKey
forall a. ToCBOR a => a -> AddressHash a
Common.addressHash VerificationKey
vk) VerificationKey
vk VerificationKey
vk

-- TODO:  we need to support password-protected secrets.
-- | Read signing key from a file.  Throw an error if the file can't be read or
-- fails to deserialise.
readEraSigningKey :: CardanoEra -> SigningKeyFile -> ExceptT ByronKeyFailure IO SigningKey
readEraSigningKey :: CardanoEra
-> SigningKeyFile -> ExceptT ByronKeyFailure IO SigningKey
readEraSigningKey CardanoEra
era (SigningKeyFile String
fp) = do
  ByteString
sK <- (IOException -> ByronKeyFailure)
-> IO ByteString -> ExceptT ByronKeyFailure IO ByteString
forall (m :: * -> *) x a.
MonadIO m =>
(IOException -> x) -> IO a -> ExceptT x m a
handleIOExceptT (String -> Text -> ByronKeyFailure
ReadSigningKeyFailure String
fp (Text -> ByronKeyFailure)
-> (IOException -> Text) -> IOException -> ByronKeyFailure
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Text
T.pack (String -> Text) -> (IOException -> String) -> IOException -> Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IOException -> String
forall e. Exception e => e -> String
displayException) (IO ByteString -> ExceptT ByronKeyFailure IO ByteString)
-> IO ByteString -> ExceptT ByronKeyFailure IO ByteString
forall a b. (a -> b) -> a -> b
$ String -> IO ByteString
LB.readFile String
fp

  -- Signing Key
  Either ByronKeyFailure SigningKey
-> ExceptT ByronKeyFailure IO SigningKey
forall (m :: * -> *) x a. Monad m => Either x a -> ExceptT x m a
hoistEither (Either ByronKeyFailure SigningKey
 -> ExceptT ByronKeyFailure IO SigningKey)
-> Either ByronKeyFailure SigningKey
-> ExceptT ByronKeyFailure IO SigningKey
forall a b. (a -> b) -> a -> b
$ CardanoEra
-> String -> ByteString -> Either ByronKeyFailure SigningKey
deserialiseSigningKey CardanoEra
era String
fp ByteString
sK

-- | Read verification key from a file.  Throw an error if the file can't be read
-- or the key fails to deserialise.
readPaymentVerificationKey :: VerificationKeyFile -> ExceptT ByronKeyFailure IO Crypto.VerificationKey
readPaymentVerificationKey :: VerificationKeyFile -> ExceptT ByronKeyFailure IO VerificationKey
readPaymentVerificationKey (VerificationKeyFile String
fp) = do
  ByteString
vkB <- (IOException -> ByronKeyFailure)
-> IO ByteString -> ExceptT ByronKeyFailure IO ByteString
forall (m :: * -> *) x a.
MonadIO m =>
(IOException -> x) -> IO a -> ExceptT x m a
handleIOExceptT (String -> Text -> ByronKeyFailure
ReadVerificationKeyFailure String
fp (Text -> ByronKeyFailure)
-> (IOException -> Text) -> IOException -> ByronKeyFailure
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Text
T.pack (String -> Text) -> (IOException -> String) -> IOException -> Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IOException -> String
forall e. Exception e => e -> String
displayException) (String -> IO ByteString
SB.readFile String
fp)
  -- Verification Key
  let eVk :: ExceptT VerificationKeyParseError IO VerificationKey
eVk = Either VerificationKeyParseError VerificationKey
-> ExceptT VerificationKeyParseError IO VerificationKey
forall (m :: * -> *) x a. Monad m => Either x a -> ExceptT x m a
hoistEither (Either VerificationKeyParseError VerificationKey
 -> ExceptT VerificationKeyParseError IO VerificationKey)
-> (String -> Either VerificationKeyParseError VerificationKey)
-> String
-> ExceptT VerificationKeyParseError IO VerificationKey
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> Either VerificationKeyParseError VerificationKey
Crypto.parseFullVerificationKey (Text -> Either VerificationKeyParseError VerificationKey)
-> (String -> Text)
-> String
-> Either VerificationKeyParseError VerificationKey
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Text
forall a. IsString a => String -> a
fromString (String -> ExceptT VerificationKeyParseError IO VerificationKey)
-> String -> ExceptT VerificationKeyParseError IO VerificationKey
forall a b. (a -> b) -> a -> b
$ ByteString -> String
UTF8.toString ByteString
vkB
  -- Convert error to 'CliError'
  (VerificationKeyParseError -> ByronKeyFailure)
-> ExceptT VerificationKeyParseError IO VerificationKey
-> ExceptT ByronKeyFailure IO VerificationKey
forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> ExceptT x m a -> ExceptT y m a
firstExceptT (String -> Text -> ByronKeyFailure
VerificationKeyDeserialisationFailed String
fp (Text -> ByronKeyFailure)
-> (VerificationKeyParseError -> Text)
-> VerificationKeyParseError
-> ByronKeyFailure
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Text
T.pack (String -> Text)
-> (VerificationKeyParseError -> String)
-> VerificationKeyParseError
-> Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. VerificationKeyParseError -> String
forall a. Show a => a -> String
show) ExceptT VerificationKeyParseError IO VerificationKey
eVk


serialisePoorKey :: CardanoEra -> Genesis.PoorSecret
                 -> Either ByronKeyFailure LB.ByteString
serialisePoorKey :: CardanoEra -> PoorSecret -> Either ByronKeyFailure ByteString
serialisePoorKey CardanoEra
ByronEraLegacy PoorSecret
ps =
  CardanoEra -> SigningKey -> Either ByronKeyFailure ByteString
serialiseSigningKey CardanoEra
ByronEraLegacy (SigningKey -> Either ByronKeyFailure ByteString)
-> SigningKey -> Either ByronKeyFailure ByteString
forall a b. (a -> b) -> a -> b
$ PoorSecret -> SigningKey
Genesis.poorSecretToKey PoorSecret
ps
serialisePoorKey CardanoEra
ByronEra PoorSecret
ps =
  CardanoEra -> SigningKey -> Either ByronKeyFailure ByteString
serialiseSigningKey CardanoEra
ByronEra (SigningKey -> Either ByronKeyFailure ByteString)
-> SigningKey -> Either ByronKeyFailure ByteString
forall a b. (a -> b) -> a -> b
$ PoorSecret -> SigningKey
Genesis.poorSecretToKey PoorSecret
ps

-- | Generate a cryptographically random signing key,
--   protected with a (potentially empty) passphrase.
keygen :: Crypto.PassPhrase -> IO SigningKey
keygen :: PassPhrase -> IO SigningKey
keygen PassPhrase
passphrase =
  (VerificationKey, SigningKey) -> SigningKey
forall a b. (a, b) -> b
snd ((VerificationKey, SigningKey) -> SigningKey)
-> IO (VerificationKey, SigningKey) -> IO SigningKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SecureRandom (VerificationKey, SigningKey)
-> IO (VerificationKey, SigningKey)
forall a. SecureRandom a -> IO a
Crypto.runSecureRandom (PassPhrase -> SecureRandom (VerificationKey, SigningKey)
forall (m :: * -> *).
MonadRandom m =>
PassPhrase -> m (VerificationKey, SigningKey)
Crypto.safeKeyGen PassPhrase
passphrase)

-- | Get a passphrase from the standard input,
--   depending on whether it's required.
getPassphrase :: PasswordPrompt -> PasswordRequirement -> IO Crypto.PassPhrase
getPassphrase :: String -> PasswordRequirement -> IO PassPhrase
getPassphrase String
desc PasswordRequirement
GetPassword   = String -> IO PassPhrase
readPassword String
desc
getPassphrase String
_    PasswordRequirement
EmptyPassword = PassPhrase -> IO PassPhrase
forall (f :: * -> *) a. Applicative f => a -> f a
pure PassPhrase
Crypto.emptyPassphrase

-- | Obtain a 'Crypto.PassPhrase' from the standard input.
--   Terminal echoing is disabled.
readPassword :: String -> IO Crypto.PassPhrase
readPassword :: String -> IO PassPhrase
readPassword String
prompt =
  ScrubbedBytes -> PassPhrase
Crypto.PassPhrase (ScrubbedBytes -> PassPhrase)
-> (ByteString -> ScrubbedBytes) -> ByteString -> PassPhrase
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ByteString -> ScrubbedBytes
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
BA.convert (ByteString -> PassPhrase) -> IO ByteString -> IO PassPhrase
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO ByteString
loop

  where
    loop :: IO ByteString
    loop :: IO ByteString
loop = do
      (ByteString
v1, ByteString
v2) <- (,) (ByteString -> ByteString -> (ByteString, ByteString))
-> IO ByteString -> IO (ByteString -> (ByteString, ByteString))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO ByteString
readOne String
prompt IO (ByteString -> (ByteString, ByteString))
-> IO ByteString -> IO (ByteString, ByteString)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> String -> IO ByteString
readOne String
"Repeat to validate: "
      if ByteString
v1 ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
v2
        then ByteString -> IO ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure ByteString
v1
        else Handle -> String -> IO ()
forall a (m :: * -> *). (Print a, MonadIO m) => Handle -> a -> m ()
hPutStrLn Handle
stdout (String
"Sorry, entered passwords don't match." :: String)
             IO () -> IO ByteString -> IO ByteString
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ByteString
loop

    readOne :: String -> IO ByteString
    readOne :: String -> IO ByteString
readOne String
pr = do
      Handle -> String -> IO ()
forall a (m :: * -> *). (Print a, MonadIO m) => Handle -> a -> m ()
hPutStr Handle
stdout String
pr IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Handle -> IO ()
hFlush Handle
stdout
      Handle -> Bool -> IO ()
hSetEcho Handle
stdout Bool
False
      ByteString
pp <- Handle -> IO ByteString
SB.hGetLine Handle
stdin
      Handle -> Bool -> IO ()
hSetEcho Handle
stdout Bool
True
      Handle -> String -> IO ()
forall a (m :: * -> *). (Print a, MonadIO m) => Handle -> a -> m ()
hPutStrLn Handle
stdout (String
"" :: String)
      ByteString -> IO ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure ByteString
pp