Use new go-wire; PubKey etc are interfaces; Keybase refactor

This commit is contained in:
Jae Kwon
2018-01-14 00:31:39 -08:00
parent 67a47e6a0b
commit 788cc0a792
25 changed files with 491 additions and 874 deletions

View File

@ -2,24 +2,20 @@ package keys_test
import (
"fmt"
"os"
"testing"
asrt "github.com/stretchr/testify/assert"
rqr "github.com/stretchr/testify/require"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
cmn "github.com/tendermint/tmlibs/common"
dbm "github.com/tendermint/tmlibs/db"
crypto "github.com/tendermint/go-crypto"
"github.com/tendermint/go-crypto"
"github.com/tendermint/go-crypto/keys"
"github.com/tendermint/go-crypto/keys/words"
"github.com/tendermint/go-crypto/nano"
)
// TestKeyManagement makes sure we can manipulate these keys well
func TestKeyManagement(t *testing.T) {
assert, require := asrt.New(t), rqr.New(t)
// make the storage with reasonable defaults
cstore := keys.New(
@ -27,84 +23,83 @@ func TestKeyManagement(t *testing.T) {
words.MustLoadCodec("english"),
)
algo := crypto.NameEd25519
algo := keys.AlgoEd25519
n1, n2, n3 := "personal", "business", "other"
p1, p2 := "1234", "really-secure!@#$"
// Check empty state
l, err := cstore.List()
require.Nil(err)
assert.Empty(l)
require.Nil(t, err)
assert.Empty(t, l)
// create some keys
_, err = cstore.Get(n1)
assert.NotNil(err)
_, i, err := cstore.Create(n1, p1, algo)
require.Equal(n1, i.Name)
require.Nil(err)
assert.NotNil(t, err)
i, _, err := cstore.Create(n1, p1, algo)
require.Equal(t, n1, i.Name)
require.Nil(t, err)
_, _, err = cstore.Create(n2, p2, algo)
require.Nil(err)
require.Nil(t, err)
// we can get these keys
i2, err := cstore.Get(n2)
assert.Nil(err)
assert.Nil(t, err)
_, err = cstore.Get(n3)
assert.NotNil(err)
assert.NotNil(t, err)
// list shows them in order
keyS, err := cstore.List()
require.Nil(err)
require.Equal(2, len(keyS))
require.Nil(t, err)
require.Equal(t, 2, len(keyS))
// note these are in alphabetical order
assert.Equal(n2, keyS[0].Name)
assert.Equal(n1, keyS[1].Name)
assert.Equal(i2.PubKey, keyS[0].PubKey)
assert.Equal(t, n2, keyS[0].Name)
assert.Equal(t, n1, keyS[1].Name)
assert.Equal(t, i2.PubKey, keyS[0].PubKey)
// deleting a key removes it
err = cstore.Delete("bad name", "foo")
require.NotNil(err)
require.NotNil(t, err)
err = cstore.Delete(n1, p1)
require.Nil(err)
require.Nil(t, err)
keyS, err = cstore.List()
require.Nil(err)
assert.Equal(1, len(keyS))
require.Nil(t, err)
assert.Equal(t, 1, len(keyS))
_, err = cstore.Get(n1)
assert.NotNil(err)
assert.NotNil(t, err)
// make sure that it only signs with the right password
// tx := mock.NewSig([]byte("mytransactiondata"))
// err = cstore.Sign(n2, p1, tx)
// assert.NotNil(err)
// assert.NotNil(t, err)
// err = cstore.Sign(n2, p2, tx)
// assert.Nil(err, "%+v", err)
// assert.Nil(t, err, "%+v", err)
// sigs, err := tx.Signers()
// assert.Nil(err, "%+v", err)
// if assert.Equal(1, len(sigs)) {
// assert.Equal(i2.PubKey, sigs[0])
// assert.Nil(t, err, "%+v", err)
// if assert.Equal(t, 1, len(sigs)) {
// assert.Equal(t, i2.PubKey, sigs[0])
// }
}
// TestSignVerify does some detailed checks on how we sign and validate
// signatures
func TestSignVerify(t *testing.T) {
assert, require := asrt.New(t), rqr.New(t)
// make the storage with reasonable defaults
cstore := keys.New(
dbm.NewMemDB(),
words.MustLoadCodec("english"),
)
algo := crypto.NameSecp256k1
algo := keys.AlgoSecp256k1
n1, n2 := "some dude", "a dudette"
p1, p2 := "1234", "foobar"
// create two users and get their info
_, i1, err := cstore.Create(n1, p1, algo)
require.Nil(err)
i1, _, err := cstore.Create(n1, p1, algo)
require.Nil(t, err)
_, i2, err := cstore.Create(n2, p2, algo)
require.Nil(err)
i2, _, err := cstore.Create(n2, p2, algo)
require.Nil(t, err)
// let's try to sign some messages
d1 := []byte("my first message")
@ -112,20 +107,20 @@ func TestSignVerify(t *testing.T) {
// try signing both data with both keys...
s11, pub1, err := cstore.Sign(n1, p1, d1)
require.Nil(err)
require.Equal(i1.PubKey, pub1)
require.Nil(t, err)
require.Equal(t, i1.PubKey, pub1)
s12, pub1, err := cstore.Sign(n1, p1, d2)
require.Nil(err)
require.Equal(i1.PubKey, pub1)
require.Nil(t, err)
require.Equal(t, i1.PubKey, pub1)
s21, pub2, err := cstore.Sign(n2, p2, d1)
require.Nil(err)
require.Equal(i2.PubKey, pub2)
require.Nil(t, err)
require.Equal(t, i2.PubKey, pub2)
s22, pub2, err := cstore.Sign(n2, p2, d2)
require.Nil(err)
require.Equal(i2.PubKey, pub2)
require.Nil(t, err)
require.Equal(t, i2.PubKey, pub2)
// let's try to validate and make sure it only works when everything is proper
cases := []struct {
@ -148,17 +143,17 @@ func TestSignVerify(t *testing.T) {
for i, tc := range cases {
valid := tc.key.VerifyBytes(tc.data, tc.sig)
assert.Equal(tc.valid, valid, "%d", i)
assert.Equal(t, tc.valid, valid, "%d", i)
}
}
/*
// TestSignWithLedger makes sure we have ledger compatibility with
// the crypto store.
//
// This test will only succeed with a ledger attached to the computer
// and the cosmos app open
func TestSignWithLedger(t *testing.T) {
assert, require := asrt.New(t), rqr.New(t)
if os.Getenv("WITH_LEDGER") == "" {
t.Skip("Set WITH_LEDGER to run code on real ledger")
}
@ -172,19 +167,19 @@ func TestSignWithLedger(t *testing.T) {
p := "hard2hack"
// create a nano user
_, c, err := cstore.Create(n, p, nano.NameLedgerEd25519)
require.Nil(err, "%+v", err)
assert.Equal(c.Name, n)
c, _, err := cstore.Create(n, p, nano.KeyLedgerEd25519)
require.Nil(t, err, "%+v", err)
assert.Equal(t, c.Key, n)
_, ok := c.PubKey.Unwrap().(nano.PubKeyLedgerEd25519)
require.True(ok)
require.True(t, ok)
// make sure we can get it back
info, err := cstore.Get(n)
require.Nil(err, "%+v", err)
assert.Equal(info.Name, n)
require.Nil(t, err, "%+v", err)
assert.Equal(t, info.Key, n)
key := info.PubKey
require.False(key.Empty())
require.True(key.Equals(c.PubKey))
require.False(t ,key.Empty())
require.True(t, key.Equals(c.PubKey))
// let's try to sign some messages
d1 := []byte("welcome to cosmos")
@ -192,56 +187,64 @@ func TestSignWithLedger(t *testing.T) {
// try signing both data with the ledger...
s1, pub, err := cstore.Sign(n, p, d1)
require.Nil(err)
require.Equal(info.PubKey, pub)
require.Nil(t, err)
require.Equal(t, info.PubKey, pub)
s2, pub, err := cstore.Sign(n, p, d2)
require.Nil(err)
require.Equal(info.PubKey, pub)
require.Nil(t, err)
require.Equal(t, info.PubKey, pub)
// now, let's check those signatures work
assert.True(key.VerifyBytes(d1, s1))
assert.True(key.VerifyBytes(d2, s2))
assert.True(t, key.VerifyBytes(d1, s1))
assert.True(t, key.VerifyBytes(d2, s2))
// and mismatched signatures don't
assert.False(key.VerifyBytes(d1, s2))
assert.False(t, key.VerifyBytes(d1, s2))
}
*/
func assertPassword(assert *asrt.Assertions, cstore keys.Keybase, name, pass, badpass string) {
func assertPassword(t *testing.T, cstore keys.Keybase, name, pass, badpass string) {
err := cstore.Update(name, badpass, pass)
assert.NotNil(err)
assert.NotNil(t, err)
err = cstore.Update(name, pass, pass)
assert.Nil(err, "%+v", err)
assert.Nil(t, err, "%+v", err)
}
// TestImportUnencrypted tests accepting raw priv keys bytes as input
func TestImportUnencrypted(t *testing.T) {
require := rqr.New(t)
// TestExportImport tests exporting and importing keys.
func TestExportImport(t *testing.T) {
// make the storage with reasonable defaults
db := dbm.NewMemDB()
cstore := keys.New(
dbm.NewMemDB(),
db,
words.MustLoadCodec("english"),
)
key := crypto.GenPrivKeyEd25519FromSecret(cmn.RandBytes(16)).Wrap()
info, _, err := cstore.Create("john", "passphrase", keys.AlgoEd25519)
assert.Nil(t, err)
assert.Equal(t, info.Name, "john")
addr := info.PubKey.Address()
addr := key.PubKey().Address()
name := "john"
pass := "top-secret"
john, err := cstore.Get("john")
assert.Nil(t, err)
assert.Equal(t, john.Name, "john")
assert.Equal(t, john.PubKey.Address(), addr)
// import raw bytes
err := cstore.Import(name, pass, "", key.Bytes())
require.Nil(err, "%+v", err)
armor, err := cstore.Export("john")
assert.Nil(t, err)
// make sure the address matches
info, err := cstore.Get(name)
require.Nil(err, "%+v", err)
require.EqualValues(addr, info.Address())
err = cstore.Import("john2", armor)
assert.Nil(t, err)
john2, err := cstore.Get("john2")
assert.Nil(t, err)
assert.Equal(t, john.PubKey.Address(), addr)
assert.Equal(t, john.Name, "john")
assert.Equal(t, john, john2)
}
// TestAdvancedKeyManagement verifies update, import, export functionality
func TestAdvancedKeyManagement(t *testing.T) {
assert, require := asrt.New(t), rqr.New(t)
// make the storage with reasonable defaults
cstore := keys.New(
@ -249,42 +252,49 @@ func TestAdvancedKeyManagement(t *testing.T) {
words.MustLoadCodec("english"),
)
algo := crypto.NameSecp256k1
algo := keys.AlgoSecp256k1
n1, n2 := "old-name", "new name"
p1, p2, p3, pt := "1234", "foobar", "ding booms!", "really-secure!@#$"
p1, p2 := "1234", "foobar"
// make sure key works with initial password
_, _, err := cstore.Create(n1, p1, algo)
require.Nil(err, "%+v", err)
assertPassword(assert, cstore, n1, p1, p2)
require.Nil(t, err, "%+v", err)
assertPassword(t, cstore, n1, p1, p2)
// update password requires the existing password
err = cstore.Update(n1, "jkkgkg", p2)
assert.NotNil(err)
assertPassword(assert, cstore, n1, p1, p2)
assert.NotNil(t, err)
assertPassword(t, cstore, n1, p1, p2)
// then it changes the password when correct
err = cstore.Update(n1, p1, p2)
assert.Nil(err)
assert.Nil(t, err)
// p2 is now the proper one!
assertPassword(assert, cstore, n1, p2, p1)
assertPassword(t, cstore, n1, p2, p1)
// exporting requires the proper name and passphrase
_, err = cstore.Export(n2, p2, pt)
assert.NotNil(err)
_, err = cstore.Export(n1, p1, pt)
assert.NotNil(err)
exported, err := cstore.Export(n1, p2, pt)
require.Nil(err, "%+v", err)
_, err = cstore.Export(n1 + ".notreal")
assert.NotNil(t, err)
_, err = cstore.Export(" " + n1)
assert.NotNil(t, err)
_, err = cstore.Export(n1 + " ")
assert.NotNil(t, err)
_, err = cstore.Export("")
assert.NotNil(t, err)
exported, err := cstore.Export(n1)
require.Nil(t, err, "%+v", err)
// import fails on bad transfer pass
err = cstore.Import(n2, p3, p2, exported)
assert.NotNil(err)
// import succeeds
err = cstore.Import(n2, exported)
assert.Nil(t, err)
// second import fails
err = cstore.Import(n2, exported)
assert.NotNil(t, err)
}
// TestSeedPhrase verifies restoring from a seed phrase
func TestSeedPhrase(t *testing.T) {
assert, require := asrt.New(t), rqr.New(t)
// make the storage with reasonable defaults
cstore := keys.New(
@ -292,28 +302,28 @@ func TestSeedPhrase(t *testing.T) {
words.MustLoadCodec("english"),
)
algo := crypto.NameEd25519
algo := keys.AlgoEd25519
n1, n2 := "lost-key", "found-again"
p1, p2 := "1234", "foobar"
// make sure key works with initial password
seed, info, err := cstore.Create(n1, p1, algo)
require.Nil(err, "%+v", err)
assert.Equal(n1, info.Name)
assert.NotEmpty(seed)
info, seed, err := cstore.Create(n1, p1, algo)
require.Nil(t, err, "%+v", err)
assert.Equal(t, n1, info.Name)
assert.NotEmpty(t, seed)
// now, let us delete this key
err = cstore.Delete(n1, p1)
require.Nil(err, "%+v", err)
require.Nil(t, err, "%+v", err)
_, err = cstore.Get(n1)
require.NotNil(err)
require.NotNil(t, err)
// let us re-create it from the seed-phrase
newInfo, err := cstore.Recover(n2, p2, algo, seed)
require.Nil(err, "%+v", err)
assert.Equal(n2, newInfo.Name)
assert.Equal(info.Address(), newInfo.Address())
assert.Equal(info.PubKey, newInfo.PubKey)
newInfo, err := cstore.Recover(n2, p2, seed)
require.Nil(t, err, "%+v", err)
assert.Equal(t, n2, newInfo.Name)
assert.Equal(t, info.Address(), newInfo.Address())
assert.Equal(t, info.PubKey, newInfo.PubKey)
}
func ExampleNew() {
@ -322,11 +332,11 @@ func ExampleNew() {
dbm.NewMemDB(),
words.MustLoadCodec("english"),
)
ed := crypto.NameEd25519
sec := crypto.NameSecp256k1
ed := keys.AlgoEd25519
sec := keys.AlgoSecp256k1
// Add keys and see they return in alphabetical order
_, bob, err := cstore.Create("Bob", "friend", ed)
bob, _, err := cstore.Create("Bob", "friend", ed)
if err != nil {
// this should never happen
fmt.Println(err)