Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

client/keys: support export of unarmored private key #8043

Merged
merged 15 commits into from
Nov 30, 2020
Prev Previous commit
Next Next commit
introduce new UnsafeKeyring interface
Unsafe operations are supported by UnsafeKeyring types.
By doing so, we try to make the client developer aware
of the risks.
  • Loading branch information
Alessio Treglia committed Nov 27, 2020
commit 685630a8dfdb1eb3bdbb527dcf2d6739b1a4cfc8
4 changes: 2 additions & 2 deletions client/keys/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/input"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
)

const (
Expand Down Expand Up @@ -37,8 +38,7 @@ func ExportKeyCommand() *cobra.Command {
}
}

hexPrivKey, err := clientCtx.Keyring.ExportPrivKeyHex(args[0])

hexPrivKey, err := keyring.NewUnsafe(clientCtx.Keyring).UnsafeExportPrivKeyHex(args[0])
if err != nil {
return err
}
Expand Down
51 changes: 39 additions & 12 deletions crypto/keyring/keyring.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ type Keyring interface {
Exporter
}

// UnsafeKeyring exposes unsafe operations such as unsafe unarmored export in
// addition to those that are made available by the Keyring interface.
type UnsafeKeyring interface {
Keyring
UnsafeExporter
}

// Signer is implemented by key stores that want to provide signing capabilities.
type Signer interface {
// Sign sign byte messages with a user key.
Expand All @@ -111,15 +118,19 @@ type Exporter interface {
ExportPubKeyArmor(uid string) (string, error)
ExportPubKeyArmorByAddress(address sdk.Address) (string, error)

// ExportPrivKeyHex returns a private key in unarmored hex format
ExportPrivKeyHex(uid string) (string, error)

// ExportPrivKey returns a private key in ASCII armored format.
// It returns an error if the key does not exist or a wrong encryption passphrase is supplied.
ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error)
ExportPrivKeyArmorByAddress(address sdk.Address, encryptPassphrase string) (armor string, err error)
}

// UnsafeExporter is implemented by key stores that support unsafe export
// of private keys' material.
type UnsafeExporter interface {
// UnsafeExportPrivKeyHex returns a private key in unarmored hex format
UnsafeExportPrivKeyHex(uid string) (string, error)
}

// Option overrides keyring configuration options.
type Option func(options *Options)

Expand Down Expand Up @@ -214,15 +225,6 @@ func (ks keystore) ExportPubKeyArmorByAddress(address sdk.Address) (string, erro
return ks.ExportPubKeyArmor(info.GetName())
}

func (ks keystore) ExportPrivKeyHex(uid string) (privkey string, err error) {
priv, err := ks.ExportPrivateKeyObject(uid)
if err != nil {
return "", err
}

return hex.EncodeToString(priv.Bytes()), nil
}

func (ks keystore) ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) {
priv, err := ks.ExportPrivateKeyObject(uid)
if err != nil {
Expand Down Expand Up @@ -787,6 +789,31 @@ func (ks keystore) writeMultisigKey(name string, pub types.PubKey) (Info, error)
return info, nil
}

type unsafeKeystore struct {
keystore
}

func newUnsafeKeystore(ks keystore) unsafeKeystore {
return unsafeKeystore{ks}
}

// NewUnsafe returns a new keyring that provides support for unsafe operations.
func NewUnsafe(kr Keyring) UnsafeKeyring {
ks := kr.(keystore)

return unsafeKeystore{ks}
}

// UnsafeExportPrivKeyHex exports private keys in unarmored hexadecimal format.
func (ks unsafeKeystore) UnsafeExportPrivKeyHex(uid string) (privkey string, err error) {
priv, err := ks.ExportPrivateKeyObject(uid)
if err != nil {
return "", err
}

return hex.EncodeToString(priv.Bytes()), nil
}

func addrHexKeyAsString(address sdk.Address) string {
return fmt.Sprintf("%s.%s", hex.EncodeToString(address.Bytes()), addressSuffix)
}