Generate/recover can return error, not panic on ledger

This commit is contained in:
Ethan Frey
2017-10-23 16:35:26 +02:00
parent 085d72d212
commit ae078ee915
5 changed files with 62 additions and 37 deletions

View File

@ -15,8 +15,10 @@ func TestNoopEncoder(t *testing.T) {
assert, require := assert.New(t), require.New(t) assert, require := assert.New(t), require.New(t)
noop := cryptostore.Noop noop := cryptostore.Noop
key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) key, err := cryptostore.GenEd25519.Generate(cmn.RandBytes(16))
key2 := cryptostore.GenSecp256k1.Generate(cmn.RandBytes(16)) require.NoError(err)
key2, err := cryptostore.GenSecp256k1.Generate(cmn.RandBytes(16))
require.NoError(err)
_, b, err := noop.Encrypt(key, "encode") _, b, err := noop.Encrypt(key, "encode")
require.Nil(err) require.Nil(err)
@ -43,7 +45,8 @@ func TestSecretBox(t *testing.T) {
assert, require := assert.New(t), require.New(t) assert, require := assert.New(t), require.New(t)
enc := cryptostore.SecretBox enc := cryptostore.SecretBox
key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) key, err := cryptostore.GenEd25519.Generate(cmn.RandBytes(16))
require.NoError(err)
pass := "some-special-secret" pass := "some-special-secret"
s, b, err := enc.Encrypt(key, pass) s, b, err := enc.Encrypt(key, pass)
@ -65,7 +68,8 @@ func TestSecretBoxNoPass(t *testing.T) {
assert, require := assert.New(t), require.New(t) assert, require := assert.New(t), require.New(t)
enc := cryptostore.SecretBox enc := cryptostore.SecretBox
key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) key, err := cryptostore.GenEd25519.Generate(cmn.RandBytes(16))
require.NoError(err)
cases := []struct { cases := []struct {
encode string encode string

View File

@ -18,57 +18,72 @@ var (
// Generator determines the type of private key the keystore creates // Generator determines the type of private key the keystore creates
type Generator interface { type Generator interface {
Generate(secret []byte) crypto.PrivKey Generate(secret []byte) (crypto.PrivKey, error)
} }
// GenFunc is a helper to transform a function into a Generator // GenFunc is a helper to transform a function into a Generator
type GenFunc func(secret []byte) crypto.PrivKey type GenFunc func(secret []byte) (crypto.PrivKey, error)
func (f GenFunc) Generate(secret []byte) crypto.PrivKey { func (f GenFunc) Generate(secret []byte) (crypto.PrivKey, error) {
return f(secret) return f(secret)
} }
func genEd25519(secret []byte) crypto.PrivKey { func genEd25519(secret []byte) (crypto.PrivKey, error) {
return crypto.GenPrivKeyEd25519FromSecret(secret).Wrap() key := crypto.GenPrivKeyEd25519FromSecret(secret).Wrap()
return key, nil
} }
func genSecp256(secret []byte) crypto.PrivKey { func genSecp256(secret []byte) (crypto.PrivKey, error) {
return crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap() key := crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap()
return key, nil
} }
// secret is completely ignored for the ledger... // secret is completely ignored for the ledger...
// just for interface compatibility // just for interface compatibility
func genLedger(secret []byte) crypto.PrivKey { func genLedger(secret []byte) (crypto.PrivKey, error) {
key, err := nano.NewPrivKeyLedger() return nano.NewPrivKeyLedger()
if err != nil {
// TODO: cleaner error handling
panic(err)
}
return key
} }
func getGenerator(algo string) (Generator, error) { type genInvalidByte struct {
typ byte
}
func (g genInvalidByte) Generate(secret []byte) (crypto.PrivKey, error) {
err := errors.Errorf("Cannot generate keys for algorithm: %X", g.typ)
return crypto.PrivKey{}, err
}
type genInvalidAlgo struct {
algo string
}
func (g genInvalidAlgo) Generate(secret []byte) (crypto.PrivKey, error) {
err := errors.Errorf("Cannot generate keys for algorithm: %s", g.algo)
return crypto.PrivKey{}, err
}
func getGenerator(algo string) Generator {
switch algo { switch algo {
case crypto.NameEd25519: case crypto.NameEd25519:
return GenEd25519, nil return GenEd25519
case crypto.NameSecp256k1: case crypto.NameSecp256k1:
return GenSecp256k1, nil return GenSecp256k1
case nano.NameLedger: case nano.NameLedger:
return GenLedger, nil return GenLedger
default: default:
return nil, errors.Errorf("Cannot generate keys for algorithm: %s", algo) return genInvalidAlgo{algo}
} }
} }
func getGeneratorByType(typ byte) (Generator, error) { func getGeneratorByType(typ byte) Generator {
switch typ { switch typ {
case crypto.TypeEd25519: case crypto.TypeEd25519:
return GenEd25519, nil return GenEd25519
case crypto.TypeSecp256k1: case crypto.TypeSecp256k1:
return GenSecp256k1, nil return GenSecp256k1
case nano.TypeLedger: case nano.TypeLedger:
return GenLedger, nil return GenLedger
default: default:
return nil, errors.Errorf("Cannot generate keys for algorithm: %X", typ) return genInvalidByte{typ}
} }
} }

View File

@ -33,14 +33,15 @@ var _ keys.Manager = Manager{}
// //
// algo must be a supported go-crypto algorithm: ed25519, secp256k1 // algo must be a supported go-crypto algorithm: ed25519, secp256k1
func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error) { func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error) {
gen, err := getGenerator(algo) // 128-bits are the all the randomness we can make use of
secret := crypto.CRandBytes(16)
gen := getGenerator(algo)
key, err := gen.Generate(secret)
if err != nil { if err != nil {
return keys.Info{}, "", err return keys.Info{}, "", err
} }
// 128-bits are the all the randomness we can make use of
secret := crypto.CRandBytes(16)
key := gen.Generate(secret)
err = s.es.Put(name, passphrase, key) err = s.es.Put(name, passphrase, key)
if err != nil { if err != nil {
return keys.Info{}, "", err return keys.Info{}, "", err
@ -74,11 +75,11 @@ func (s Manager) Recover(name, passphrase, seedphrase string) (keys.Info, error)
l := len(secret) l := len(secret)
secret, typ := secret[:l-1], secret[l-1] secret, typ := secret[:l-1], secret[l-1]
gen, err := getGeneratorByType(typ) gen := getGeneratorByType(typ)
key, err := gen.Generate(secret)
if err != nil { if err != nil {
return keys.Info{}, err return keys.Info{}, err
} }
key := gen.Generate(secret)
// d00d, it worked! create the bugger.... // d00d, it worked! create the bugger....
err = s.es.Put(name, passphrase, key) err = s.es.Put(name, passphrase, key)

View File

@ -224,13 +224,15 @@ func TestImportUnencrypted(t *testing.T) {
keys.MustLoadCodec("english"), keys.MustLoadCodec("english"),
) )
key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) key, err := cryptostore.GenEd25519.Generate(cmn.RandBytes(16))
require.NoError(err)
addr := key.PubKey().Address() addr := key.PubKey().Address()
name := "john" name := "john"
pass := "top-secret" pass := "top-secret"
// import raw bytes // import raw bytes
err := cstore.Import(name, pass, "", nil, key.Bytes()) err = cstore.Import(name, pass, "", nil, key.Bytes())
require.Nil(err, "%+v", err) require.Nil(err, "%+v", err)
// make sure the address matches // make sure the address matches

View File

@ -14,7 +14,10 @@ import (
func TestSortKeys(t *testing.T) { func TestSortKeys(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
gen := func() crypto.PrivKey { return GenEd25519.Generate(cmn.RandBytes(16)) } gen := func() crypto.PrivKey {
key, _ := GenEd25519.Generate(cmn.RandBytes(16))
return key
}
assert.NotEqual(gen(), gen()) assert.NotEqual(gen(), gen())
// alphabetical order is n3, n1, n2 // alphabetical order is n3, n1, n2