Merge PR #5439: Keybase: Multiple Signature Algorithms

This commit is contained in:
Sunny Aggarwal
2020-01-14 10:40:10 -05:00
committed by Alexander Bezobchuk
parent d452e9398b
commit f367087731
21 changed files with 419 additions and 201 deletions
+34 -28
View File
@@ -10,7 +10,6 @@ import (
cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
"github.com/cosmos/cosmos-sdk/crypto/keys/keyerror"
"github.com/cosmos/cosmos-sdk/crypto/keys/mintkey"
"github.com/cosmos/cosmos-sdk/types"
@@ -57,7 +56,7 @@ const (
var (
// ErrUnsupportedSigningAlgo is raised when the caller tries to use a
// different signing scheme than secp256k1.
ErrUnsupportedSigningAlgo = errors.New("unsupported signing algo: only secp256k1 is supported")
ErrUnsupportedSigningAlgo = errors.New("unsupported signing algo")
// ErrUnsupportedLanguage is raised when the caller tries to use a
// different language than english for creating a mnemonic sentence.
@@ -101,18 +100,10 @@ func (kb dbKeybase) CreateMnemonic(
// CreateAccount converts a mnemonic to a private key and persists it, encrypted
// with the given password.
func (kb dbKeybase) CreateAccount(
name, mnemonic, bip39Passwd, encryptPasswd string, account uint32, index uint32,
name, mnemonic, bip39Passwd, encryptPasswd, hdPath string, algo SigningAlgo,
) (Info, error) {
return kb.base.CreateAccount(kb, name, mnemonic, bip39Passwd, encryptPasswd, account, index)
}
// Derive computes a BIP39 seed from th mnemonic and bip39Passwd.
func (kb dbKeybase) Derive(
name, mnemonic, bip39Passphrase, encryptPasswd string, params hd.BIP44Params,
) (Info, error) {
return kb.base.Derive(kb, name, mnemonic, bip39Passphrase, encryptPasswd, params)
return kb.base.CreateAccount(kb, name, mnemonic, bip39Passwd, encryptPasswd, hdPath, algo)
}
// CreateLedger creates a new locally-stored reference to a Ledger keypair.
@@ -126,8 +117,8 @@ func (kb dbKeybase) CreateLedger(
// CreateOffline creates a new reference to an offline keypair. It returns the
// created key info.
func (kb dbKeybase) CreateOffline(name string, pub tmcrypto.PubKey) (Info, error) {
return kb.base.writeOfflineKey(kb, name, pub), nil
func (kb dbKeybase) CreateOffline(name string, pub tmcrypto.PubKey, algo SigningAlgo) (Info, error) {
return kb.base.writeOfflineKey(kb, name, pub, algo), nil
}
// CreateMulti creates a new reference to a multisig (offline) keypair. It
@@ -199,7 +190,7 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig []byte, pub t
return
}
priv, err = mintkey.UnarmorDecryptPrivKey(i.PrivKeyArmor, passphrase)
priv, _, err = mintkey.UnarmorDecryptPrivKey(i.PrivKeyArmor, passphrase)
if err != nil {
return nil, nil, err
}
@@ -238,7 +229,7 @@ func (kb dbKeybase) ExportPrivateKeyObject(name string, passphrase string) (tmcr
return nil, err
}
priv, err = mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase)
priv, _, err = mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase)
if err != nil {
return nil, err
}
@@ -272,7 +263,7 @@ func (kb dbKeybase) ExportPubKey(name string) (armor string, err error) {
return
}
return mintkey.ArmorPubKeyBytes(info.GetPubKey().Bytes()), nil
return mintkey.ArmorPubKeyBytes(info.GetPubKey().Bytes(), string(info.GetAlgo())), nil
}
// ExportPrivKey returns a private key in ASCII armored format.
@@ -285,7 +276,12 @@ func (kb dbKeybase) ExportPrivKey(name string, decryptPassphrase string,
return "", err
}
return mintkey.EncryptArmorPrivKey(priv, encryptPassphrase), nil
info, err := kb.Get(name)
if err != nil {
return "", err
}
return mintkey.EncryptArmorPrivKey(priv, encryptPassphrase, string(info.GetAlgo())), nil
}
// ImportPrivKey imports a private key in ASCII armor format. It returns an
@@ -296,12 +292,12 @@ func (kb dbKeybase) ImportPrivKey(name string, armor string, passphrase string)
return errors.New("Cannot overwrite key " + name)
}
privKey, err := mintkey.UnarmorDecryptPrivKey(armor, passphrase)
privKey, algo, err := mintkey.UnarmorDecryptPrivKey(armor, passphrase)
if err != nil {
return errors.Wrap(err, "couldn't import private key")
}
kb.writeLocalKey(name, privKey, passphrase)
kb.writeLocalKey(name, privKey, passphrase, SigningAlgo(algo))
return nil
}
@@ -329,7 +325,7 @@ func (kb dbKeybase) ImportPubKey(name string, armor string) (err error) {
return errors.New("Cannot overwrite data for name " + name)
}
pubBytes, err := mintkey.UnarmorPubKeyBytes(armor)
pubBytes, algo, err := mintkey.UnarmorPubKeyBytes(armor)
if err != nil {
return
}
@@ -339,7 +335,7 @@ func (kb dbKeybase) ImportPubKey(name string, armor string) (err error) {
return
}
kb.base.writeOfflineKey(kb, name, pubKey)
kb.base.writeOfflineKey(kb, name, pubKey, SigningAlgo(algo))
return
}
@@ -355,7 +351,7 @@ func (kb dbKeybase) Delete(name, passphrase string, skipPass bool) error {
}
if linfo, ok := info.(localInfo); ok && !skipPass {
if _, err = mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase); err != nil {
if _, _, err = mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase); err != nil {
return err
}
}
@@ -382,7 +378,7 @@ func (kb dbKeybase) Update(name, oldpass string, getNewpass func() (string, erro
case localInfo:
linfo := i
key, err := mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, oldpass)
key, _, err := mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, oldpass)
if err != nil {
return err
}
@@ -392,7 +388,7 @@ func (kb dbKeybase) Update(name, oldpass string, getNewpass func() (string, erro
return err
}
kb.writeLocalKey(name, key, newpass)
kb.writeLocalKey(name, key, newpass, i.GetAlgo())
return nil
default:
@@ -405,13 +401,23 @@ func (kb dbKeybase) CloseDB() {
kb.db.Close()
}
func (kb dbKeybase) writeLocalKey(name string, priv tmcrypto.PrivKey, passphrase string) Info {
// SupportedAlgos returns a list of supported signing algorithms.
func (kb dbKeybase) SupportedAlgos() []SigningAlgo {
return kb.base.SupportedAlgos()
}
// SupportedAlgosLedger returns a list of supported ledger signing algorithms.
func (kb dbKeybase) SupportedAlgosLedger() []SigningAlgo {
return kb.base.SupportedAlgosLedger()
}
func (kb dbKeybase) writeLocalKey(name string, priv tmcrypto.PrivKey, passphrase string, algo SigningAlgo) Info {
// encrypt private key using passphrase
privArmor := mintkey.EncryptArmorPrivKey(priv, passphrase)
privArmor := mintkey.EncryptArmorPrivKey(priv, passphrase, string(algo))
// make Info
pub := priv.PubKey()
info := newLocalInfo(name, pub, privArmor)
info := newLocalInfo(name, pub, privArmor, algo)
kb.writeInfo(name, info)
return info
+107 -54
View File
@@ -17,7 +17,10 @@ import (
type (
kbOptions struct {
keygenFunc PrivKeyGenFunc
keygenFunc PrivKeyGenFunc
deriveFunc DeriveKeyFunc
supportedAlgos []SigningAlgo
supportedAlgosLedger []SigningAlgo
}
// baseKeybase is an auxiliary type that groups Keybase storage agnostic features
@@ -32,7 +35,7 @@ type (
}
writeLocalKeyer interface {
writeLocalKey(name string, priv tmcrypto.PrivKey, passphrase string) Info
writeLocalKey(name string, priv tmcrypto.PrivKey, passphrase string, algo SigningAlgo) Info
}
infoWriter interface {
@@ -47,10 +50,36 @@ func WithKeygenFunc(f PrivKeyGenFunc) KeybaseOption {
}
}
// WithDeriveFunc applies an overridden key derivation function to generate the private key.
func WithDeriveFunc(f DeriveKeyFunc) KeybaseOption {
return func(o *kbOptions) {
o.deriveFunc = f
}
}
// WithSupportedAlgos defines the list of accepted SigningAlgos.
func WithSupportedAlgos(algos []SigningAlgo) KeybaseOption {
return func(o *kbOptions) {
o.supportedAlgos = algos
}
}
// WithSupportedAlgosLedger defines the list of accepted SigningAlgos compatible with Ledger.
func WithSupportedAlgosLedger(algos []SigningAlgo) KeybaseOption {
return func(o *kbOptions) {
o.supportedAlgosLedger = algos
}
}
// newBaseKeybase generates the base keybase with defaulting to tendermint SECP256K1 key type
func newBaseKeybase(optionsFns ...KeybaseOption) baseKeybase {
// Default options for keybase
options := kbOptions{keygenFunc: baseSecpPrivKeyGen}
options := kbOptions{
keygenFunc: StdPrivKeyGen,
deriveFunc: StdDeriveKey,
supportedAlgos: []SigningAlgo{Secp256k1},
supportedAlgosLedger: []SigningAlgo{Secp256k1},
}
for _, optionFn := range optionsFns {
optionFn(&options)
@@ -59,9 +88,20 @@ func newBaseKeybase(optionsFns ...KeybaseOption) baseKeybase {
return baseKeybase{options: options}
}
// baseSecpPrivKeyGen generates a secp256k1 private key from the given bytes
func baseSecpPrivKeyGen(bz [32]byte) tmcrypto.PrivKey {
return secp256k1.PrivKeySecp256k1(bz)
// StdPrivKeyGen is the default PrivKeyGen function in the keybase.
// For now, it only supports Secp256k1
func StdPrivKeyGen(bz []byte, algo SigningAlgo) (tmcrypto.PrivKey, error) {
if algo == Secp256k1 {
return SecpPrivKeyGen(bz), nil
}
return nil, ErrUnsupportedSigningAlgo
}
// SecpPrivKeyGen generates a secp256k1 private key from the given bytes
func SecpPrivKeyGen(bz []byte) tmcrypto.PrivKey {
var bzArr [32]byte
copy(bzArr[:], bz)
return secp256k1.PrivKeySecp256k1(bzArr)
}
// SignWithLedger signs a binary message with the ledger device referenced by an Info object
@@ -111,29 +151,26 @@ func (kb baseKeybase) DecodeSignature(info Info, msg []byte) (sig []byte, pub tm
// CreateAccount creates an account Info object.
func (kb baseKeybase) CreateAccount(
keyWriter keyWriter, name, mnemonic, bip39Passwd, encryptPasswd string, account, index uint32,
) (Info, error) {
hdPath := CreateHDPath(account, index)
return kb.Derive(keyWriter, name, mnemonic, bip39Passwd, encryptPasswd, *hdPath)
}
func (kb baseKeybase) persistDerivedKey(
keyWriter keyWriter, seed []byte, passwd, name, fullHdPath string,
keyWriter keyWriter, name, mnemonic, bip39Passphrase, encryptPasswd, hdPath string, algo SigningAlgo,
) (Info, error) {
// create master key and derive first key for keyring
derivedPriv, err := ComputeDerivedKey(seed, fullHdPath)
derivedPriv, err := kb.options.deriveFunc(mnemonic, bip39Passphrase, hdPath, algo)
if err != nil {
return nil, err
}
privKey, err := kb.options.keygenFunc(derivedPriv, algo)
if err != nil {
return nil, err
}
var info Info
if passwd != "" {
info = keyWriter.writeLocalKey(name, kb.options.keygenFunc(derivedPriv), passwd)
if encryptPasswd != "" {
info = keyWriter.writeLocalKey(name, privKey, encryptPasswd, algo)
} else {
info = kb.writeOfflineKey(keyWriter, name, kb.options.keygenFunc(derivedPriv).PubKey())
info = kb.writeOfflineKey(keyWriter, name, privKey.PubKey(), algo)
}
return info, nil
@@ -145,7 +182,7 @@ func (kb baseKeybase) CreateLedger(
w infoWriter, name string, algo SigningAlgo, hrp string, account, index uint32,
) (Info, error) {
if !IsAlgoSupported(algo) {
if !IsSupportedAlgorithm(kb.SupportedAlgosLedger(), algo) {
return nil, ErrUnsupportedSigningAlgo
}
@@ -157,7 +194,7 @@ func (kb baseKeybase) CreateLedger(
return nil, err
}
return kb.writeLedgerKey(w, name, priv.PubKey(), *hdPath), nil
return kb.writeLedgerKey(w, name, priv.PubKey(), *hdPath, algo), nil
}
// CreateMnemonic generates a new key with the given algorithm and language pair.
@@ -169,7 +206,7 @@ func (kb baseKeybase) CreateMnemonic(
return nil, "", ErrUnsupportedLanguage
}
if !IsAlgoSupported(algo) {
if !IsSupportedAlgorithm(kb.SupportedAlgos(), algo) {
return nil, "", ErrUnsupportedSigningAlgo
}
@@ -185,37 +222,22 @@ func (kb baseKeybase) CreateMnemonic(
return nil, "", err
}
info, err = kb.persistDerivedKey(
keyWriter,
bip39.NewSeed(mnemonic, DefaultBIP39Passphrase), passwd,
name, types.GetConfig().GetFullFundraiserPath(),
)
info, err = kb.CreateAccount(keyWriter, name, mnemonic, DefaultBIP39Passphrase, passwd, types.GetConfig().GetFullFundraiserPath(), algo)
if err != nil {
return nil, "", err
}
return info, mnemonic, err
}
// Derive computes a BIP39 seed from the mnemonic and bip39Passphrase. It creates
// a private key from the seed using the BIP44 params.
func (kb baseKeybase) Derive(
keyWriter keyWriter, name, mnemonic, bip39Passphrase, encryptPasswd string, params hd.BIP44Params, // nolint:interfacer
) (Info, error) {
seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase)
if err != nil {
return nil, err
}
return kb.persistDerivedKey(keyWriter, seed, encryptPasswd, name, params.String())
}
func (kb baseKeybase) writeLedgerKey(w infoWriter, name string, pub tmcrypto.PubKey, path hd.BIP44Params) Info {
info := newLedgerInfo(name, pub, path)
func (kb baseKeybase) writeLedgerKey(w infoWriter, name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo SigningAlgo) Info {
info := newLedgerInfo(name, pub, path, algo)
w.writeInfo(name, info)
return info
}
func (kb baseKeybase) writeOfflineKey(w infoWriter, name string, pub tmcrypto.PubKey) Info {
info := newOfflineInfo(name, pub)
func (kb baseKeybase) writeOfflineKey(w infoWriter, name string, pub tmcrypto.PubKey, algo SigningAlgo) Info {
info := newOfflineInfo(name, pub, algo)
w.writeInfo(name, info)
return info
}
@@ -226,10 +248,28 @@ func (kb baseKeybase) writeMultisigKey(w infoWriter, name string, pub tmcrypto.P
return info
}
// ComputeDerivedKey derives and returns the private key for the given seed and HD path.
func ComputeDerivedKey(seed []byte, fullHdPath string) ([32]byte, error) {
// StdDeriveKey is the default DeriveKey function in the keybase.
// For now, it only supports Secp256k1
func StdDeriveKey(mnemonic string, bip39Passphrase, hdPath string, algo SigningAlgo) ([]byte, error) {
if algo == Secp256k1 {
return SecpDeriveKey(mnemonic, bip39Passphrase, hdPath)
}
return nil, ErrUnsupportedSigningAlgo
}
// SecpDeriveKey derives and returns the secp256k1 private key for the given seed and HD path.
func SecpDeriveKey(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) {
seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase)
if err != nil {
return nil, err
}
masterPriv, ch := hd.ComputeMastersFromSeed(seed)
return hd.DerivePrivateKeyForPath(masterPriv, ch, fullHdPath)
if len(hdPath) == 0 {
return masterPriv[:], nil
}
derivedKey, err := hd.DerivePrivateKeyForPath(masterPriv, ch, hdPath)
return derivedKey[:], err
}
// CreateHDPath returns BIP 44 object from account and index parameters.
@@ -237,9 +277,22 @@ func CreateHDPath(account uint32, index uint32) *hd.BIP44Params {
return hd.NewFundraiserParams(account, types.GetConfig().GetCoinType(), index)
}
// IsAlgoSupported returns whether the signing algorithm is supported.
//
// TODO: Refactor this to be configurable to support interchangeable key signing
// and addressing.
// Ref: https://github.com/cosmos/cosmos-sdk/issues/4941
func IsAlgoSupported(algo SigningAlgo) bool { return algo == Secp256k1 }
// SupportedAlgos returns a list of supported signing algorithms.
func (kb baseKeybase) SupportedAlgos() []SigningAlgo {
return kb.options.supportedAlgos
}
// SupportedAlgosLedger returns a list of supported ledger signing algorithms.
func (kb baseKeybase) SupportedAlgosLedger() []SigningAlgo {
return kb.options.supportedAlgosLedger
}
// IsSupportedAlgorithm returns whether the signing algorithm is in the passed-in list of supported algorithms.
func IsSupportedAlgorithm(supported []SigningAlgo, algo SigningAlgo) bool {
for _, supportedAlgo := range supported {
if algo == supportedAlgo {
return true
}
}
return false
}
+46 -7
View File
@@ -38,25 +38,43 @@ func TestCreateAccountInvalidMnemonic(t *testing.T) {
_, err := kb.CreateAccount(
"some_account",
"malarkey pair crucial catch public canyon evil outer stage ten gym tornado",
"", "", 0, 1)
"", "", CreateHDPath(0, 0).String(), Secp256k1)
assert.Error(t, err)
assert.Equal(t, "Invalid mnemonic", err.Error())
}
func TestCreateLedgerUnsupportedAlgo(t *testing.T) {
kb := NewInMemory()
supportedLedgerAlgos := kb.SupportedAlgosLedger()
for _, supportedAlgo := range supportedLedgerAlgos {
if Ed25519 == supportedAlgo {
assert.FailNow(t, "Was not an unsupported algorithm")
}
}
_, err := kb.CreateLedger("some_account", Ed25519, "cosmos", 0, 1)
assert.Error(t, err)
assert.Equal(t, "unsupported signing algo: only secp256k1 is supported", err.Error())
assert.Equal(t, "unsupported signing algo", err.Error())
}
func TestCreateLedger(t *testing.T) {
kb := NewInMemory()
kb := NewInMemory(WithSupportedAlgosLedger([]SigningAlgo{Secp256k1, Ed25519}))
// test_cover and test_unit will result in different answers
// test_cover does not compile some dependencies so ledger is disabled
// test_unit may add a ledger mock
// both cases are acceptable
supportedLedgerAlgos := kb.SupportedAlgosLedger()
secpSupported := false
edSupported := false
for _, supportedAlgo := range supportedLedgerAlgos {
secpSupported = secpSupported || (supportedAlgo == Secp256k1)
edSupported = edSupported || (supportedAlgo == Ed25519)
}
assert.True(t, secpSupported)
assert.True(t, edSupported)
ledger, err := kb.CreateLedger("some_account", Secp256k1, "cosmos", 3, 1)
if err != nil {
@@ -92,7 +110,21 @@ func TestCreateLedger(t *testing.T) {
// TestKeyManagement makes sure we can manipulate these keys well
func TestKeyManagement(t *testing.T) {
// make the storage with reasonable defaults
cstore := NewInMemory()
cstore := NewInMemory(WithSupportedAlgos([]SigningAlgo{Secp256k1, Sr25519}))
// Test modified supported algos
supportedAlgos := cstore.SupportedAlgos()
secpSupported := false
edSupported := false
srSupported := false
for _, supportedAlgo := range supportedAlgos {
secpSupported = secpSupported || (supportedAlgo == Secp256k1)
edSupported = edSupported || (supportedAlgo == Ed25519)
srSupported = srSupported || (supportedAlgo == Sr25519)
}
assert.True(t, secpSupported)
assert.False(t, edSupported)
assert.True(t, srSupported)
algo := Secp256k1
n1, n2, n3 := "personal", "business", "other"
@@ -152,10 +184,12 @@ func TestKeyManagement(t *testing.T) {
o1 := "offline"
priv1 := ed25519.GenPrivKey()
pub1 := priv1.PubKey()
i, err = cstore.CreateOffline(o1, pub1)
i, err = cstore.CreateOffline(o1, pub1, algo)
require.Nil(t, err)
require.Equal(t, pub1, i.GetPubKey())
require.Equal(t, o1, i.GetName())
iOffline := i.(*offlineInfo)
require.Equal(t, algo, iOffline.GetAlgo())
keyS, err = cstore.List()
require.NoError(t, err)
require.Equal(t, 2, len(keyS))
@@ -393,7 +427,8 @@ func TestSeedPhrase(t *testing.T) {
// let us re-create it from the mnemonic-phrase
params := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
newInfo, err := cstore.Derive(n2, mnemonic, DefaultBIP39Passphrase, p2, params)
hdPath := params.String()
newInfo, err := cstore.CreateAccount(n2, mnemonic, DefaultBIP39Passphrase, p2, hdPath, Secp256k1)
require.NoError(t, err)
require.Equal(t, n2, newInfo.GetName())
require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address())
@@ -402,7 +437,11 @@ func TestSeedPhrase(t *testing.T) {
func ExampleNew() {
// Select the encryption and storage for your cryptostore
customKeyGenFunc := func(bz [32]byte) crypto.PrivKey { return secp256k1.PrivKeySecp256k1(bz) }
customKeyGenFunc := func(bz []byte, algo SigningAlgo) (crypto.PrivKey, error) {
var bzArr [32]byte
copy(bzArr[:], bz)
return secp256k1.PrivKeySecp256k1(bzArr), nil
}
cstore := NewInMemory(WithKeygenFunc(customKeyGenFunc))
sec := Secp256k1
+29 -24
View File
@@ -20,7 +20,6 @@ import (
cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino"
"github.com/cosmos/cosmos-sdk/client/input"
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
"github.com/cosmos/cosmos-sdk/crypto/keys/keyerror"
"github.com/cosmos/cosmos-sdk/crypto/keys/mintkey"
"github.com/cosmos/cosmos-sdk/types"
@@ -90,19 +89,10 @@ func (kb keyringKeybase) CreateMnemonic(
// CreateAccount converts a mnemonic to a private key and persists it, encrypted
// with the given password.
func (kb keyringKeybase) CreateAccount(
name, mnemonic, bip39Passwd, encryptPasswd string, account, index uint32,
name, mnemonic, bip39Passwd, encryptPasswd, hdPath string, algo SigningAlgo,
) (Info, error) {
return kb.base.CreateAccount(kb, name, mnemonic, bip39Passwd, encryptPasswd, account, index)
}
// Derive computes a BIP39 seed from th mnemonic and bip39Passphrase. It creates
// a private key from the seed using the BIP44 params.
func (kb keyringKeybase) Derive(
name, mnemonic, bip39Passphrase, encryptPasswd string, params hd.BIP44Params,
) (info Info, err error) {
return kb.base.Derive(kb, name, mnemonic, bip39Passphrase, encryptPasswd, params)
return kb.base.CreateAccount(kb, name, mnemonic, bip39Passwd, encryptPasswd, hdPath, algo)
}
// CreateLedger creates a new locally-stored reference to a Ledger keypair.
@@ -116,8 +106,8 @@ func (kb keyringKeybase) CreateLedger(
// CreateOffline creates a new reference to an offline keypair. It returns the
// created key info.
func (kb keyringKeybase) CreateOffline(name string, pub tmcrypto.PubKey) (Info, error) {
return kb.base.writeOfflineKey(kb, name, pub), nil
func (kb keyringKeybase) CreateOffline(name string, pub tmcrypto.PubKey, algo SigningAlgo) (Info, error) {
return kb.base.writeOfflineKey(kb, name, pub, algo), nil
}
// CreateMulti creates a new reference to a multisig (offline) keypair. It
@@ -284,7 +274,7 @@ func (kb keyringKeybase) ExportPubKey(name string) (armor string, err error) {
return "", fmt.Errorf("no key to export with name: %s", name)
}
return mintkey.ArmorPubKeyBytes(bz.GetPubKey().Bytes()), nil
return mintkey.ArmorPubKeyBytes(bz.GetPubKey().Bytes(), string(bz.GetAlgo())), nil
}
// Import imports armored private key.
@@ -330,7 +320,12 @@ func (kb keyringKeybase) ExportPrivKey(name, decryptPassphrase, encryptPassphras
return "", err
}
return mintkey.EncryptArmorPrivKey(priv, encryptPassphrase), nil
info, err := kb.Get(name)
if err != nil {
return "", err
}
return mintkey.EncryptArmorPrivKey(priv, encryptPassphrase, string(info.GetAlgo())), nil
}
// ImportPrivKey imports a private key in ASCII armor format. An error is returned
@@ -341,13 +336,13 @@ func (kb keyringKeybase) ImportPrivKey(name, armor, passphrase string) error {
return fmt.Errorf("cannot overwrite key: %s", name)
}
privKey, err := mintkey.UnarmorDecryptPrivKey(armor, passphrase)
privKey, algo, err := mintkey.UnarmorDecryptPrivKey(armor, passphrase)
if err != nil {
return errors.Wrap(err, "failed to decrypt private key")
}
// NOTE: The keyring keystore has no need for a passphrase.
kb.writeLocalKey(name, privKey, "")
kb.writeLocalKey(name, privKey, "", SigningAlgo(algo))
return nil
}
@@ -370,7 +365,7 @@ func (kb keyringKeybase) ImportPubKey(name string, armor string) error {
}
}
pubBytes, err := mintkey.UnarmorPubKeyBytes(armor)
pubBytes, algo, err := mintkey.UnarmorPubKeyBytes(armor)
if err != nil {
return err
}
@@ -380,7 +375,7 @@ func (kb keyringKeybase) ImportPubKey(name string, armor string) error {
return err
}
kb.base.writeOfflineKey(kb, name, pubKey)
kb.base.writeOfflineKey(kb, name, pubKey, SigningAlgo(algo))
return nil
}
@@ -419,7 +414,7 @@ func (kb keyringKeybase) Update(name, oldpass string, getNewpass func() (string,
switch linfo := info.(type) {
case localInfo:
key, err := mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, oldpass)
key, _, err := mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, oldpass)
if err != nil {
return err
}
@@ -429,7 +424,7 @@ func (kb keyringKeybase) Update(name, oldpass string, getNewpass func() (string,
return err
}
kb.writeLocalKey(name, key, newpass)
kb.writeLocalKey(name, key, newpass, linfo.GetAlgo())
return nil
default:
@@ -437,13 +432,23 @@ func (kb keyringKeybase) Update(name, oldpass string, getNewpass func() (string,
}
}
// SupportedAlgos returns a list of supported signing algorithms.
func (kb keyringKeybase) SupportedAlgos() []SigningAlgo {
return kb.base.SupportedAlgos()
}
// SupportedAlgosLedger returns a list of supported ledger signing algorithms.
func (kb keyringKeybase) SupportedAlgosLedger() []SigningAlgo {
return kb.base.SupportedAlgosLedger()
}
// CloseDB releases the lock and closes the storage backend.
func (kb keyringKeybase) CloseDB() {}
func (kb keyringKeybase) writeLocalKey(name string, priv tmcrypto.PrivKey, _ string) Info {
func (kb keyringKeybase) writeLocalKey(name string, priv tmcrypto.PrivKey, _ string, algo SigningAlgo) Info {
// encrypt private key using keyring
pub := priv.PubKey()
info := newLocalInfo(name, pub, string(priv.Bytes()))
info := newLocalInfo(name, pub, string(priv.Bytes()), algo)
kb.writeInfo(name, info)
return info
+5 -3
View File
@@ -79,7 +79,7 @@ func TestLazyKeyManagementKeyRing(t *testing.T) {
o1 := "offline"
priv1 := ed25519.GenPrivKey()
pub1 := priv1.PubKey()
i, err = kb.CreateOffline(o1, pub1)
i, err = kb.CreateOffline(o1, pub1, Ed25519)
require.Nil(t, err)
require.Equal(t, pub1, i.GetPubKey())
require.Equal(t, o1, i.GetName())
@@ -209,10 +209,11 @@ func TestLazyExportImportPubKeyKeyRing(t *testing.T) {
defer cleanup()
kb, err := NewTestKeyring("keybasename", dir)
require.NoError(t, err)
algo := Secp256k1
// CreateMnemonic a private-public key pair and ensure consistency
notPasswd := "n9y25ah7"
info, _, err := kb.CreateMnemonic("john", English, notPasswd, Secp256k1)
info, _, err := kb.CreateMnemonic("john", English, notPasswd, algo)
require.Nil(t, err)
require.NotEqual(t, info, "")
require.Equal(t, info.GetName(), "john")
@@ -318,7 +319,8 @@ func TestLazySeedPhraseKeyRing(t *testing.T) {
// let us re-create it from the mnemonic-phrase
params := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
newInfo, err := kb.Derive(n2, mnemonic, DefaultBIP39Passphrase, p2, params)
hdPath := params.String()
newInfo, err := kb.CreateAccount(n2, mnemonic, DefaultBIP39Passphrase, p2, hdPath, Secp256k1)
require.NoError(t, err)
require.Equal(t, n2, newInfo.GetName())
require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address())
+4
View File
@@ -4,9 +4,13 @@ package keys
type SigningAlgo string
const (
// MultiAlgo implies that a pubkey is a multisignature
MultiAlgo = SigningAlgo("multi")
// Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters.
Secp256k1 = SigningAlgo("secp256k1")
// Ed25519 represents the Ed25519 signature system.
// It is currently not supported for end-user keys (wallets/ledgers).
Ed25519 = SigningAlgo("ed25519")
// Sr25519 represents the Sr25519 signature system.
Sr25519 = SigningAlgo("sr25519")
)
+14 -15
View File
@@ -6,7 +6,6 @@ import (
"github.com/tendermint/tendermint/crypto"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@@ -88,7 +87,7 @@ func (lkb lazyKeybase) CreateMnemonic(name string, language Language, passwd str
return newDBKeybase(db, lkb.options...).CreateMnemonic(name, language, passwd, algo)
}
func (lkb lazyKeybase) CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd string, account uint32, index uint32) (Info, error) {
func (lkb lazyKeybase) CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd, hdPath string, algo SigningAlgo) (Info, error) {
db, err := sdk.NewLevelDB(lkb.name, lkb.dir)
if err != nil {
return nil, err
@@ -96,17 +95,7 @@ func (lkb lazyKeybase) CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd
defer db.Close()
return newDBKeybase(db,
lkb.options...).CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd, account, index)
}
func (lkb lazyKeybase) Derive(name, mnemonic, bip39Passwd, encryptPasswd string, params hd.BIP44Params) (Info, error) {
db, err := sdk.NewLevelDB(lkb.name, lkb.dir)
if err != nil {
return nil, err
}
defer db.Close()
return newDBKeybase(db, lkb.options...).Derive(name, mnemonic, bip39Passwd, encryptPasswd, params)
lkb.options...).CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd, hdPath, algo)
}
func (lkb lazyKeybase) CreateLedger(name string, algo SigningAlgo, hrp string, account, index uint32) (info Info, err error) {
@@ -119,14 +108,14 @@ func (lkb lazyKeybase) CreateLedger(name string, algo SigningAlgo, hrp string, a
return newDBKeybase(db, lkb.options...).CreateLedger(name, algo, hrp, account, index)
}
func (lkb lazyKeybase) CreateOffline(name string, pubkey crypto.PubKey) (info Info, err error) {
func (lkb lazyKeybase) CreateOffline(name string, pubkey crypto.PubKey, algo SigningAlgo) (info Info, err error) {
db, err := sdk.NewLevelDB(lkb.name, lkb.dir)
if err != nil {
return nil, err
}
defer db.Close()
return newDBKeybase(db, lkb.options...).CreateOffline(name, pubkey)
return newDBKeybase(db, lkb.options...).CreateOffline(name, pubkey, algo)
}
func (lkb lazyKeybase) CreateMulti(name string, pubkey crypto.PubKey) (info Info, err error) {
@@ -221,4 +210,14 @@ func (lkb lazyKeybase) ExportPrivKey(name string, decryptPassphrase string,
return newDBKeybase(db, lkb.options...).ExportPrivKey(name, decryptPassphrase, encryptPassphrase)
}
// SupportedAlgos returns a list of supported signing algorithms.
func (lkb lazyKeybase) SupportedAlgos() []SigningAlgo {
return newBaseKeybase(lkb.options...).SupportedAlgos()
}
// SupportedAlgosLedger returns a list of supported ledger signing algorithms.
func (lkb lazyKeybase) SupportedAlgosLedger() []SigningAlgo {
return newBaseKeybase(lkb.options...).SupportedAlgosLedger()
}
func (lkb lazyKeybase) CloseDB() {}
+7 -5
View File
@@ -89,7 +89,7 @@ func TestLazyKeyManagement(t *testing.T) {
o1 := "offline"
priv1 := ed25519.GenPrivKey()
pub1 := priv1.PubKey()
i, err = kb.CreateOffline(o1, pub1)
i, err = kb.CreateOffline(o1, pub1, algo)
require.Nil(t, err)
require.Equal(t, pub1, i.GetPubKey())
require.Equal(t, o1, i.GetName())
@@ -245,10 +245,11 @@ func TestLazyExportImportPubKey(t *testing.T) {
dir, cleanup := tests.NewTestCaseDir(t)
defer cleanup()
kb := New("keybasename", dir)
algo := Secp256k1
// CreateMnemonic a private-public key pair and ensure consistency
notPasswd := "n9y25ah7"
info, _, err := kb.CreateMnemonic("john", English, notPasswd, Secp256k1)
info, _, err := kb.CreateMnemonic("john", English, notPasswd, algo)
require.Nil(t, err)
require.NotEqual(t, info, "")
require.Equal(t, info.GetName(), "john")
@@ -368,7 +369,8 @@ func TestLazySeedPhrase(t *testing.T) {
// let us re-create it from the mnemonic-phrase
params := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
newInfo, err := kb.Derive(n2, mnemonic, DefaultBIP39Passphrase, p2, params)
hdPath := params.String()
newInfo, err := kb.CreateAccount(n2, mnemonic, DefaultBIP39Passphrase, p2, hdPath, algo)
require.NoError(t, err)
require.Equal(t, n2, newInfo.GetName())
require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address())
@@ -421,9 +423,9 @@ func TestKeygenOverride(t *testing.T) {
CryptoCdc = testCdc
overrideCalled := false
dummyFunc := func(bz [32]byte) crypto.PrivKey {
dummyFunc := func(bz []byte, algo SigningAlgo) (crypto.PrivKey, error) {
overrideCalled = true
return testPriv(bz[:])
return testPriv(bz[:]), nil
}
kb := New("keybasename", dir, WithKeygenFunc(dummyFunc))
+58 -29
View File
@@ -20,6 +20,11 @@ const (
blockTypePrivKey = "TENDERMINT PRIVATE KEY"
blockTypeKeyInfo = "TENDERMINT KEY INFO"
blockTypePubKey = "TENDERMINT PUBLIC KEY"
defaultAlgo = "secp256k1"
headerVersion = "version"
headerType = "type"
)
// Make bcrypt security parameter var, so it can be changed within the lcd test
@@ -42,36 +47,58 @@ var BcryptSecurityParameter = 12
// Armor the InfoBytes
func ArmorInfoBytes(bz []byte) string {
return armorBytes(bz, blockTypeKeyInfo)
header := map[string]string{
headerType: "Info",
headerVersion: "0.0.0",
}
return armor.EncodeArmor(blockTypeKeyInfo, header, bz)
}
// Armor the PubKeyBytes
func ArmorPubKeyBytes(bz []byte) string {
return armorBytes(bz, blockTypePubKey)
}
func armorBytes(bz []byte, blockType string) string {
func ArmorPubKeyBytes(bz []byte, algo string) string {
header := map[string]string{
"type": "Info",
"version": "0.0.0",
headerVersion: "0.0.1",
}
return armor.EncodeArmor(blockType, header, bz)
if algo != "" {
header[headerType] = algo
}
return armor.EncodeArmor(blockTypePubKey, header, bz)
}
//-----------------------------------------------------------------
// remove armor
// Unarmor the InfoBytes
func UnarmorInfoBytes(armorStr string) (bz []byte, err error) {
return unarmorBytes(armorStr, blockTypeKeyInfo)
func UnarmorInfoBytes(armorStr string) ([]byte, error) {
bz, header, err := unarmorBytes(armorStr, blockTypeKeyInfo)
if err != nil {
return nil, err
}
if header[headerVersion] != "0.0.0" {
return nil, fmt.Errorf("unrecognized version: %v", header[headerVersion])
}
return bz, nil
}
// Unarmor the PubKeyBytes
func UnarmorPubKeyBytes(armorStr string) (bz []byte, err error) {
return unarmorBytes(armorStr, blockTypePubKey)
// UnarmorPubKeyBytes returns the pubkey byte slice, a string of the algo type, and an error
func UnarmorPubKeyBytes(armorStr string) (bz []byte, algo string, err error) {
bz, header, err := unarmorBytes(armorStr, blockTypePubKey)
switch header[headerVersion] {
case "0.0.0":
return bz, defaultAlgo, err
case "0.0.1":
if header[headerType] == "" {
header[headerType] = defaultAlgo
}
return bz, header[headerType], err
default:
err = fmt.Errorf("unrecognized version: %v", header[headerVersion])
return nil, "", err
}
}
func unarmorBytes(armorStr, blockType string) (bz []byte, err error) {
func unarmorBytes(armorStr, blockType string) (bz []byte, header map[string]string, err error) {
bType, header, bz, err := armor.DecodeArmor(armorStr)
if err != nil {
return
@@ -80,10 +107,6 @@ func unarmorBytes(armorStr, blockType string) (bz []byte, err error) {
err = fmt.Errorf("unrecognized armor type %q, expected: %q", bType, blockType)
return
}
if header["version"] != "0.0.0" {
err = fmt.Errorf("unrecognized version: %v", header["version"])
return
}
return
}
@@ -91,12 +114,15 @@ func unarmorBytes(armorStr, blockType string) (bz []byte, err error) {
// encrypt/decrypt with armor
// Encrypt and armor the private key.
func EncryptArmorPrivKey(privKey crypto.PrivKey, passphrase string) string {
func EncryptArmorPrivKey(privKey crypto.PrivKey, passphrase string, algo string) string {
saltBytes, encBytes := encryptPrivKey(privKey, passphrase)
header := map[string]string{
"kdf": "bcrypt",
"salt": fmt.Sprintf("%X", saltBytes),
}
if algo != "" {
header[headerType] = algo
}
armorStr := armor.EncodeArmor(blockTypePrivKey, header, encBytes)
return armorStr
}
@@ -115,28 +141,31 @@ func encryptPrivKey(privKey crypto.PrivKey, passphrase string) (saltBytes []byte
return saltBytes, xsalsa20symmetric.EncryptSymmetric(privKeyBytes, key)
}
// Unarmor and decrypt the private key.
func UnarmorDecryptPrivKey(armorStr string, passphrase string) (crypto.PrivKey, error) {
var privKey crypto.PrivKey
// UnarmorDecryptPrivKey returns the privkey byte slice, a string of the algo type, and an error
func UnarmorDecryptPrivKey(armorStr string, passphrase string) (privKey crypto.PrivKey, algo string, err error) {
blockType, header, encBytes, err := armor.DecodeArmor(armorStr)
if err != nil {
return privKey, err
return privKey, "", err
}
if blockType != blockTypePrivKey {
return privKey, fmt.Errorf("unrecognized armor type: %v", blockType)
return privKey, "", fmt.Errorf("unrecognized armor type: %v", blockType)
}
if header["kdf"] != "bcrypt" {
return privKey, fmt.Errorf("unrecognized KDF type: %v", header["KDF"])
return privKey, "", fmt.Errorf("unrecognized KDF type: %v", header["KDF"])
}
if header["salt"] == "" {
return privKey, fmt.Errorf("missing salt bytes")
return privKey, "", fmt.Errorf("missing salt bytes")
}
saltBytes, err := hex.DecodeString(header["salt"])
if err != nil {
return privKey, fmt.Errorf("error decoding salt: %v", err.Error())
return privKey, "", fmt.Errorf("error decoding salt: %v", err.Error())
}
privKey, err = decryptPrivKey(saltBytes, encBytes, passphrase)
return privKey, err
if header[headerType] == "" {
header[headerType] = defaultAlgo
}
return privKey, header[headerType], err
}
func decryptPrivKey(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) {
+7 -5
View File
@@ -13,11 +13,12 @@ import (
func TestArmorUnarmorPrivKey(t *testing.T) {
priv := secp256k1.GenPrivKey()
armor := mintkey.EncryptArmorPrivKey(priv, "passphrase")
_, err := mintkey.UnarmorDecryptPrivKey(armor, "wrongpassphrase")
armor := mintkey.EncryptArmorPrivKey(priv, "passphrase", "")
_, _, err := mintkey.UnarmorDecryptPrivKey(armor, "wrongpassphrase")
require.Error(t, err)
decrypted, err := mintkey.UnarmorDecryptPrivKey(armor, "passphrase")
decrypted, algo, err := mintkey.UnarmorDecryptPrivKey(armor, "passphrase")
require.NoError(t, err)
require.Equal(t, string(keys.Secp256k1), algo)
require.True(t, priv.Equals(decrypted))
}
@@ -28,10 +29,11 @@ func TestArmorUnarmorPubKey(t *testing.T) {
// Add keys and see they return in alphabetical order
info, _, err := cstore.CreateMnemonic("Bob", keys.English, "passphrase", keys.Secp256k1)
require.NoError(t, err)
armor := mintkey.ArmorPubKeyBytes(info.GetPubKey().Bytes())
pubBytes, err := mintkey.UnarmorPubKeyBytes(armor)
armor := mintkey.ArmorPubKeyBytes(info.GetPubKey().Bytes(), "")
pubBytes, algo, err := mintkey.UnarmorPubKeyBytes(armor)
require.NoError(t, err)
pub, err := cryptoAmino.PubKeyFromBytes(pubBytes)
require.NoError(t, err)
require.Equal(t, string(keys.Secp256k1), algo)
require.True(t, pub.Equals(info.GetPubKey()))
}
+43 -13
View File
@@ -31,21 +31,15 @@ type Keybase interface {
// same name.
CreateMnemonic(name string, language Language, passwd string, algo SigningAlgo) (info Info, seed string, err error)
// CreateAccount converts a mnemonic to a private key using a BIP44 path 44'/118'/{account}'/0/{index}
// CreateAccount converts a mnemonic to a private key and BIP 32 HD Path
// and persists it, encrypted with the given password.
CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd string, account uint32, index uint32) (Info, error)
// Derive computes a BIP39 seed from th mnemonic and bip39Passwd.
// Derive private key from the seed using the BIP44 params.
// Encrypt the key to disk using encryptPasswd.
// See https://github.com/cosmos/cosmos-sdk/issues/2095
Derive(name, mnemonic, bip39Passwd, encryptPasswd string, params hd.BIP44Params) (Info, error)
CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd, hdPath string, algo SigningAlgo) (Info, error)
// CreateLedger creates, stores, and returns a new Ledger key reference
CreateLedger(name string, algo SigningAlgo, hrp string, account, index uint32) (info Info, err error)
// CreateOffline creates, stores, and returns a new offline key reference
CreateOffline(name string, pubkey crypto.PubKey) (info Info, err error)
CreateOffline(name string, pubkey crypto.PubKey, algo SigningAlgo) (info Info, err error)
// CreateMulti creates, stores, and returns a new multsig (offline) key reference
CreateMulti(name string, pubkey crypto.PubKey) (info Info, err error)
@@ -81,6 +75,12 @@ type Keybase interface {
// ExportPrivateKeyObject *only* works on locally-stored keys. Temporary method until we redo the exporting API
ExportPrivateKeyObject(name string, passphrase string) (crypto.PrivKey, error)
// SupportedAlgos returns a list of signing algorithms supported by the keybase
SupportedAlgos() []SigningAlgo
// SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration
SupportedAlgosLedger() []SigningAlgo
// CloseDB closes the database.
CloseDB()
}
@@ -118,6 +118,8 @@ type Info interface {
GetPubKey() crypto.PubKey
// Address
GetAddress() types.AccAddress
// Algo
GetAlgo() SigningAlgo
// Bip44 Path
GetPath() (*hd.BIP44Params, error)
}
@@ -132,15 +134,17 @@ var (
// localInfo is the public information about a locally stored key
type localInfo struct {
Name string `json:"name"`
Algo SigningAlgo `json:"algo"`
PubKey crypto.PubKey `json:"pubkey"`
PrivKeyArmor string `json:"privkey.armor"`
}
func newLocalInfo(name string, pub crypto.PubKey, privArmor string) Info {
func newLocalInfo(name string, pub crypto.PubKey, privArmor string, algo SigningAlgo) Info {
return &localInfo{
Name: name,
PubKey: pub,
PrivKeyArmor: privArmor,
Algo: algo,
}
}
@@ -164,6 +168,11 @@ func (i localInfo) GetAddress() types.AccAddress {
return i.PubKey.Address().Bytes()
}
// GetType implements Info interface
func (i localInfo) GetAlgo() SigningAlgo {
return i.Algo
}
// GetType implements Info interface
func (i localInfo) GetPath() (*hd.BIP44Params, error) {
return nil, fmt.Errorf("BIP44 Paths are not available for this type")
@@ -174,13 +183,15 @@ type ledgerInfo struct {
Name string `json:"name"`
PubKey crypto.PubKey `json:"pubkey"`
Path hd.BIP44Params `json:"path"`
Algo SigningAlgo `json:"algo"`
}
func newLedgerInfo(name string, pub crypto.PubKey, path hd.BIP44Params) Info {
func newLedgerInfo(name string, pub crypto.PubKey, path hd.BIP44Params, algo SigningAlgo) Info {
return &ledgerInfo{
Name: name,
PubKey: pub,
Path: path,
Algo: algo,
}
}
@@ -204,6 +215,11 @@ func (i ledgerInfo) GetAddress() types.AccAddress {
return i.PubKey.Address().Bytes()
}
// GetPath implements Info interface
func (i ledgerInfo) GetAlgo() SigningAlgo {
return i.Algo
}
// GetPath implements Info interface
func (i ledgerInfo) GetPath() (*hd.BIP44Params, error) {
tmp := i.Path
@@ -213,13 +229,15 @@ func (i ledgerInfo) GetPath() (*hd.BIP44Params, error) {
// offlineInfo is the public information about an offline key
type offlineInfo struct {
Name string `json:"name"`
Algo SigningAlgo `json:"algo"`
PubKey crypto.PubKey `json:"pubkey"`
}
func newOfflineInfo(name string, pub crypto.PubKey) Info {
func newOfflineInfo(name string, pub crypto.PubKey, algo SigningAlgo) Info {
return &offlineInfo{
Name: name,
PubKey: pub,
Algo: algo,
}
}
@@ -238,6 +256,11 @@ func (i offlineInfo) GetPubKey() crypto.PubKey {
return i.PubKey
}
// GetAlgo returns the signing algorithm for the key
func (i offlineInfo) GetAlgo() SigningAlgo {
return i.Algo
}
// GetAddress implements Info interface
func (i offlineInfo) GetAddress() types.AccAddress {
return i.PubKey.Address().Bytes()
@@ -299,6 +322,11 @@ func (i multiInfo) GetAddress() types.AccAddress {
return i.PubKey.Address().Bytes()
}
// GetPath implements Info interface
func (i multiInfo) GetAlgo() SigningAlgo {
return MultiAlgo
}
// GetPath implements Info interface
func (i multiInfo) GetPath() (*hd.BIP44Params, error) {
return nil, fmt.Errorf("BIP44 Paths are not available for this type")
@@ -316,8 +344,10 @@ func unmarshalInfo(bz []byte) (info Info, err error) {
}
type (
// DeriveKeyFunc defines the function to derive a new key from a seed and hd path
DeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string, algo SigningAlgo) ([]byte, error)
// PrivKeyGenFunc defines the function to convert derived key bytes to a tendermint private key
PrivKeyGenFunc func(bz [32]byte) crypto.PrivKey
PrivKeyGenFunc func(bz []byte, algo SigningAlgo) (crypto.PrivKey, error)
// KeybaseOption overrides options for the db
KeybaseOption func(*kbOptions)
+1 -1
View File
@@ -17,7 +17,7 @@ func Test_writeReadLedgerInfo(t *testing.T) {
bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A")
copy(tmpKey[:], bz)
lInfo := newLedgerInfo("some_name", tmpKey, *hd.NewFundraiserParams(5, types.CoinType, 1))
lInfo := newLedgerInfo("some_name", tmpKey, *hd.NewFundraiserParams(5, types.CoinType, 1), Secp256k1)
assert.Equal(t, TypeLedger, lInfo.GetType())
path, err := lInfo.GetPath()