diff --git a/circle.yml b/circle.yml index a37187dd9..af63a0594 100644 --- a/circle.yml +++ b/circle.yml @@ -18,4 +18,4 @@ dependencies: test: override: - "go version" - - "cd $PROJECT_PATH && make all" + - "cd $PROJECT_PATH && make get_tools && make all" diff --git a/bcrypt/base64.go b/keys/bcrypt/base64.go similarity index 100% rename from bcrypt/base64.go rename to keys/bcrypt/base64.go diff --git a/bcrypt/bcrypt.go b/keys/bcrypt/bcrypt.go similarity index 100% rename from bcrypt/bcrypt.go rename to keys/bcrypt/bcrypt.go diff --git a/hd/address.go b/keys/hd/address.go similarity index 54% rename from hd/address.go rename to keys/hd/address.go index f59876739..9511ffad2 100644 --- a/hd/address.go +++ b/keys/hd/address.go @@ -21,19 +21,30 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcutil/base58" - "github.com/tendermint/go-crypto" "golang.org/x/crypto/ripemd160" ) -func ComputeAddress(pubKeyHex string, chainHex string, path string, index int32) string { +/* + + This file implements BIP32 HD wallets. + Note it only works for SECP256k1 keys. + It also includes some Bitcoin specific utility functions. + +*/ + +// ComputeBTCAddress returns the BTC address using the pubKeyHex and chainCodeHex +// for the given path and index. +func ComputeBTCAddress(pubKeyHex string, chainCodeHex string, path string, index int32) string { pubKeyBytes := DerivePublicKeyForPath( HexDecode(pubKeyHex), - HexDecode(chainHex), + HexDecode(chainCodeHex), fmt.Sprintf("%v/%v", path, index), ) - return AddrFromPubKeyBytes(pubKeyBytes) + return BTCAddrFromPubKeyBytes(pubKeyBytes) } +// ComputePrivateKey returns the private key using the master mprivHex and chainCodeHex +// for the given path and index. func ComputePrivateKey(mprivHex string, chainHex string, path string, index int32) string { privKeyBytes := DerivePrivateKeyForPath( HexDecode(mprivHex), @@ -43,12 +54,14 @@ func ComputePrivateKey(mprivHex string, chainHex string, path string, index int3 return HexEncode(privKeyBytes) } -func ComputeAddressForPrivKey(privKey string) string { +// ComputeBTCAddressForPrivKey returns the Bitcoin address for the given privKey. +func ComputeBTCAddressForPrivKey(privKey string) string { pubKeyBytes := PubKeyBytesFromPrivKeyBytes(HexDecode(privKey), true) - return AddrFromPubKeyBytes(pubKeyBytes) + return BTCAddrFromPubKeyBytes(pubKeyBytes) } -func SignMessage(privKey string, message string, compress bool) string { +// SignBTCMessage signs a "Bitcoin Signed Message". +func SignBTCMessage(privKey string, message string, compress bool) string { prefixBytes := []byte("Bitcoin Signed Message:\n") messageBytes := []byte(message) bytes := []byte{} @@ -67,25 +80,28 @@ func SignMessage(privKey string, message string, compress bool) string { PublicKey: ecdsaPubKey, D: new(big.Int).SetBytes(privKeyBytes), } - sigbytes, err := btcec.SignCompact(btcec.S256(), ecdsaPrivKey, crypto.Sha256(crypto.Sha256(bytes)), compress) + sigbytes, err := btcec.SignCompact(btcec.S256(), ecdsaPrivKey, CalcHash256(bytes), compress) if err != nil { panic(err) } return base64.StdEncoding.EncodeToString(sigbytes) } -// returns MPK, Chain, and master secret in hex. -func ComputeMastersFromSeed(seed string) (string, string, string, string) { - secret, chain := I64([]byte("Bitcoin seed"), []byte(seed)) +// ComputeMastersFromSeed returns the master public key, master secret, and chain code in hex. +func ComputeMastersFromSeed(seed string) (string, string, string) { + key, data := []byte("Bitcoin seed"), []byte(seed) + secret, chain := I64(key, data) pubKeyBytes := PubKeyBytesFromPrivKeyBytes(secret, true) - return HexEncode(pubKeyBytes), HexEncode(secret), HexEncode(chain), HexEncode(secret) + return HexEncode(pubKeyBytes), HexEncode(secret), HexEncode(chain) } +// ComputeWIF returns the privKey in Wallet Import Format. func ComputeWIF(privKey string, compress bool) string { return WIFFromPrivKeyBytes(HexDecode(privKey), compress) } -func ComputeTxId(rawTxHex string) string { +// ComputeBTCTxId returns the bitcoin transaction ID. +func ComputeBTCTxId(rawTxHex string) string { return HexEncode(ReverseBytes(CalcHash256(HexDecode(rawTxHex)))) } @@ -103,7 +119,11 @@ func printKeyInfo(privKeyBytes []byte, pubKeyBytes []byte, chain []byte) { } */ -func DerivePrivateKeyForPath(privKeyBytes []byte, chain []byte, path string) []byte { +//------------------------------------------------------------------- + +// DerivePrivateKeyForPath derives the private key by following the path from privKeyBytes, +// using the given chainCode. +func DerivePrivateKeyForPath(privKeyBytes []byte, chainCode []byte, path string) []byte { data := privKeyBytes parts := strings.Split(path, "/") for _, part := range parts { @@ -119,13 +139,15 @@ func DerivePrivateKeyForPath(privKeyBytes []byte, chain []byte, path string) []b if i < 0 { panic(errors.New("index too large.")) } - data, chain = DerivePrivateKey(data, chain, uint32(i), prime) + data, chainCode = DerivePrivateKey(data, chainCode, uint32(i), prime) //printKeyInfo(data, nil, chain) } return data } -func DerivePublicKeyForPath(pubKeyBytes []byte, chain []byte, path string) []byte { +// DerivePublicKeyForPath derives the public key by following the path from pubKeyBytes +// using the given chainCode. +func DerivePublicKeyForPath(pubKeyBytes []byte, chainCode []byte, path string) []byte { data := pubKeyBytes parts := strings.Split(path, "/") for _, part := range parts { @@ -140,36 +162,42 @@ func DerivePublicKeyForPath(pubKeyBytes []byte, chain []byte, path string) []byt if i < 0 { panic(errors.New("index too large.")) } - data, chain = DerivePublicKey(data, chain, uint32(i)) - //printKeyInfo(nil, data, chain) + data, chainCode = DerivePublicKey(data, chainCode, uint32(i)) + //printKeyInfo(nil, data, chainCode) } return data } -func DerivePrivateKey(privKeyBytes []byte, chain []byte, i uint32, prime bool) ([]byte, []byte) { +// DerivePrivateKey derives the private key with index and chainCode. +// If prime is true, the derivation is 'hardened'. +// It returns the new private key and new chain code. +func DerivePrivateKey(privKeyBytes []byte, chainCode []byte, index uint32, prime bool) ([]byte, []byte) { var data []byte if prime { - i = i | 0x80000000 + index = index | 0x80000000 data = append([]byte{byte(0)}, privKeyBytes...) } else { public := PubKeyBytesFromPrivKeyBytes(privKeyBytes, true) data = public } - data = append(data, uint32ToBytes(i)...) - data2, chain2 := I64(chain, data) + data = append(data, uint32ToBytes(index)...) + data2, chainCode2 := I64(chainCode, data) x := addScalars(privKeyBytes, data2) - return x, chain2 + return x, chainCode2 } -func DerivePublicKey(pubKeyBytes []byte, chain []byte, i uint32) ([]byte, []byte) { +// DerivePublicKey derives the public key with index and chainCode. +// It returns the new public key and new chain code. +func DerivePublicKey(pubKeyBytes []byte, chainCode []byte, index uint32) ([]byte, []byte) { data := []byte{} data = append(data, pubKeyBytes...) - data = append(data, uint32ToBytes(i)...) - data2, chain2 := I64(chain, data) + data = append(data, uint32ToBytes(index)...) + data2, chainCode2 := I64(chainCode, data) data2p := PubKeyBytesFromPrivKeyBytes(data2, true) - return addPoints(pubKeyBytes, data2p), chain2 + return addPoints(pubKeyBytes, data2p), chainCode2 } +// eliptic curve pubkey addition func addPoints(a []byte, b []byte) []byte { ap, err := btcec.ParsePubKey(a, btcec.S256()) if err != nil { @@ -188,6 +216,7 @@ func addPoints(a []byte, b []byte) []byte { return sum.SerializeCompressed() } +// modular big endian addition func addScalars(a []byte, b []byte) []byte { aInt := new(big.Int).SetBytes(a) bInt := new(big.Int).SetBytes(b) @@ -204,15 +233,21 @@ func uint32ToBytes(i uint32) []byte { return b[:] } +//------------------------------------------------------------------- + +// HexEncode encodes b in hex. func HexEncode(b []byte) string { return hex.EncodeToString(b) } +// HexDecode hex decodes the str. If str is not valid hex +// it will return an empty byte slice. func HexDecode(str string) []byte { b, _ := hex.DecodeString(str) return b } +// I64 returns the two halfs of the SHA512 HMAC of key and data. func I64(key []byte, data []byte) ([]byte, []byte) { mac := hmac.New(sha512.New, key) mac.Write(data) @@ -220,27 +255,36 @@ func I64(key []byte, data []byte) ([]byte, []byte) { return I[:32], I[32:] } -// This returns a Bitcoin-like address. -func AddrFromPubKeyBytes(pubKeyBytes []byte) string { - prefix := byte(0x00) // TODO Make const or configurable +//------------------------------------------------------------------- + +const ( + btcPrefixPubKeyHash = byte(0x00) + btcPrefixPrivKey = byte(0x80) +) + +// BTCAddrFromPubKeyBytes returns a B58 encoded Bitcoin mainnet address. +func BTCAddrFromPubKeyBytes(pubKeyBytes []byte) string { + versionPrefix := btcPrefixPubKeyHash // TODO Make const or configurable h160 := CalcHash160(pubKeyBytes) - h160 = append([]byte{prefix}, h160...) + h160 = append([]byte{versionPrefix}, h160...) checksum := CalcHash256(h160) b := append(h160, checksum[:4]...) return base58.Encode(b) } -func AddrBytesFromPubKeyBytes(pubKeyBytes []byte) (addrBytes []byte, checksum []byte) { - prefix := byte(0x00) // TODO Make const or configurable +// BTCAddrBytesFromPubKeyBytes returns a hex Bitcoin mainnet address and its checksum. +func BTCAddrBytesFromPubKeyBytes(pubKeyBytes []byte) (addrBytes []byte, checksum []byte) { + versionPrefix := btcPrefixPubKeyHash // TODO Make const or configurable h160 := CalcHash160(pubKeyBytes) - _h160 := append([]byte{prefix}, h160...) + _h160 := append([]byte{versionPrefix}, h160...) checksum = CalcHash256(_h160)[:4] return h160, checksum } +// WIFFromPrivKeyBytes returns the privKeyBytes in Wallet Import Format. func WIFFromPrivKeyBytes(privKeyBytes []byte, compress bool) string { - prefix := byte(0x80) // TODO Make const or configurable - bytes := append([]byte{prefix}, privKeyBytes...) + versionPrefix := btcPrefixPrivKey // TODO Make const or configurable + bytes := append([]byte{versionPrefix}, privKeyBytes...) if compress { bytes = append(bytes, byte(1)) } @@ -249,6 +293,7 @@ func WIFFromPrivKeyBytes(privKeyBytes []byte, compress bool) string { return base58.Encode(bytes) } +// PubKeyBytesFromPrivKeyBytes returns the optionally compressed public key bytes. func PubKeyBytesFromPrivKeyBytes(privKeyBytes []byte, compress bool) (pubKeyBytes []byte) { x, y := btcec.S256().ScalarBaseMult(privKeyBytes) pub := &btcec.PublicKey{ @@ -263,27 +308,30 @@ func PubKeyBytesFromPrivKeyBytes(privKeyBytes []byte, compress bool) (pubKeyByte return pub.SerializeUncompressed() } -// Calculate the hash of hasher over buf. -func CalcHash(buf []byte, hasher hash.Hash) []byte { - hasher.Write(buf) +//-------------------------------------------------------------- + +// CalcHash returns the hash of data using hasher. +func CalcHash(data []byte, hasher hash.Hash) []byte { + hasher.Write(data) return hasher.Sum(nil) } -// calculate hash160 which is ripemd160(sha256(data)) -func CalcHash160(buf []byte) []byte { - return CalcHash(CalcHash(buf, sha256.New()), ripemd160.New()) +// CalcHash160 returns the ripemd160(sha256(data)). +func CalcHash160(data []byte) []byte { + return CalcHash(CalcHash(data, sha256.New()), ripemd160.New()) } -// calculate hash256 which is sha256(sha256(data)) -func CalcHash256(buf []byte) []byte { - return CalcHash(CalcHash(buf, sha256.New()), sha256.New()) +// CalcHash256 returns the sha256(sha256(data)). +func CalcHash256(data []byte) []byte { + return CalcHash(CalcHash(data, sha256.New()), sha256.New()) } -// calculate sha512(data) -func CalcSha512(buf []byte) []byte { - return CalcHash(buf, sha512.New()) +// CalcSha512 returns the sha512(data). +func CalcSha512(data []byte) []byte { + return CalcHash(data, sha512.New()) } +// ReverseBytes returns the buf in the opposite order func ReverseBytes(buf []byte) []byte { var res []byte if len(buf) == 0 { diff --git a/hd/address_test.go b/keys/hd/address_test.go similarity index 100% rename from hd/address_test.go rename to keys/hd/address_test.go diff --git a/hd/hd_test.go b/keys/hd/hd_test.go similarity index 98% rename from hd/hd_test.go rename to keys/hd/hd_test.go index 0ec47f5c3..c9e540ad5 100644 --- a/hd/hd_test.go +++ b/keys/hd/hd_test.go @@ -112,7 +112,7 @@ func ifExit(err error, n int) { func gocrypto(seed []byte) ([]byte, []byte, []byte) { - _, priv, ch, _ := ComputeMastersFromSeed(string(seed)) + _, priv, ch := ComputeMastersFromSeed(string(seed)) privBytes := DerivePrivateKeyForPath( HexDecode(priv), diff --git a/hd/test.json b/keys/hd/test.json similarity index 100% rename from hd/test.json rename to keys/hd/test.json diff --git a/keys/keybase.go b/keys/keybase.go index c68564d5a..c72518748 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -8,6 +8,7 @@ import ( crypto "github.com/tendermint/go-crypto" dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/go-crypto/keys/words" "github.com/tendermint/go-crypto/nano" ) @@ -19,10 +20,10 @@ import ( // a full-featured key manager type dbKeybase struct { db dbm.DB - codec Codec + codec words.Codec } -func New(db dbm.DB, codec Codec) dbKeybase { +func New(db dbm.DB, codec words.Codec) dbKeybase { return dbKeybase{ db: db, codec: codec, @@ -31,59 +32,61 @@ func New(db dbm.DB, codec Codec) dbKeybase { var _ Keybase = dbKeybase{} -// Create adds a new key to the storage engine, returning error if -// another key already stored under this name -// -// algo must be a supported go-crypto algorithm: ed25519, secp256k1 -func (kb dbKeybase) Create(name, passphrase, algo string) (Info, string, error) { - // 128-bits are the all the randomness we can make use of +// Create generates a new key and persists it storage, encrypted using the passphrase. +// It returns the generated seedphrase (mnemonic) and the key Info. +// It returns an error if it fails to generate a key for the given algo type, +// or if another key is already stored under the same name. +func (kb dbKeybase) Create(name, passphrase, algo string) (string, Info, error) { + // NOTE: secret is SHA256 hashed by secp256k1 and ed25519. + // 16 byte secret corresponds to 12 BIP39 words. + // XXX: Ledgers use 24 words now - should we ? secret := crypto.CRandBytes(16) key, err := generate(algo, secret) if err != nil { - return Info{}, "", err + return "", Info{}, err } + // encrypt and persist the key public := kb.writeKey(key, name, passphrase) - // we append the type byte to the serialized secret to help with recovery - // ie [secret] = [secret] + [type] - typ := key.Bytes()[0] - secret = append(secret, typ) - - seed, err := kb.codec.BytesToWords(secret) - phrase := strings.Join(seed, " ") - return public, phrase, err + // return the mnemonic phrase + words, err := kb.codec.BytesToWords(secret) + seedphrase := strings.Join(words, " ") + return seedphrase, public, err } -// Recover takes a seed phrase and tries to recover the private key. -// -// If the seed phrase is valid, it will create the private key and store -// it under name, protected by passphrase. -// -// Result similar to New(), except it doesn't return the seed again... -func (kb dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { +// Recover converts a seedphrase to a private key and persists it, encrypted with the given passphrase. +// Functions like Create, but seedphrase is input not output. +func (kb dbKeybase) Recover(name, passphrase, algo string, seedphrase string) (Info, error) { + + key, err := kb.SeedToPrivKey(algo, seedphrase) + if err != nil { + return Info{}, err + } + + // Valid seedphrase. Encrypt key and persist to disk. + public := kb.writeKey(key, name, passphrase) + return public, nil +} + +// SeedToPrivKey returns the private key corresponding to a seedphrase +// without persisting the private key. +// TODO: enable the keybase to just hold these in memory so we can sign without persisting (?) +func (kb dbKeybase) SeedToPrivKey(algo, seedphrase string) (crypto.PrivKey, error) { words := strings.Split(strings.TrimSpace(seedphrase), " ") secret, err := kb.codec.WordsToBytes(words) if err != nil { - return Info{}, err + return crypto.PrivKey{}, err } - // secret is comprised of the actual secret with the type appended - // ie [secret] = [secret] + [type] - l := len(secret) - secret, typ := secret[:l-1], secret[l-1] - - key, err := generateByType(typ, secret) + key, err := generate(algo, secret) if err != nil { - return Info{}, err + return crypto.PrivKey{}, err } - - // d00d, it worked! create the bugger.... - public := kb.writeKey(key, name, passphrase) - return public, err + return key, nil } -// List loads the keys from the storage and enforces alphabetical order +// List returns the keys from storage in alphabetical order. func (kb dbKeybase) List() ([]Info, error) { var res []Info iter := kb.db.Iterator(nil, nil) @@ -101,20 +104,19 @@ func (kb dbKeybase) List() ([]Info, error) { return res, nil } -// Get returns the public information about one key +// Get returns the public information about one key. func (kb dbKeybase) Get(name string) (Info, error) { bs := kb.db.Get(pubName(name)) return readInfo(bs) } -// Sign will modify the Signable in order to attach a valid signature with -// this public key -// -// If no key for this name, or the passphrase doesn't match, returns an error +// Sign signs the msg with the named key. +// It returns an error if the key doesn't exist or the decryption fails. +// TODO: what if leddger fails ? func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signature, pk crypto.PubKey, err error) { var key crypto.PrivKey - bs := kb.db.Get(privName(name)) - key, err = unarmorDecryptPrivKey(string(bs), passphrase) + armorStr := kb.db.Get(privName(name)) + key, err = unarmorDecryptPrivKey(string(armorStr), passphrase) if err != nil { return } @@ -124,15 +126,15 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signat return } -// Export decodes the private key with the current password, encodes -// it with a secure one-time password and generates a sequence that can be -// Imported by another dbKeybase +// Export decodes the private key with the current password, encrypts +// it with a secure one-time password and generates an armored private key +// that can be Imported by another dbKeybase. // // This is designed to copy from one device to another, or provide backups // during version updates. func (kb dbKeybase) Export(name, oldpass, transferpass string) ([]byte, error) { - bs := kb.db.Get(privName(name)) - key, err := unarmorDecryptPrivKey(string(bs), oldpass) + armorStr := kb.db.Get(privName(name)) + key, err := unarmorDecryptPrivKey(string(armorStr), oldpass) if err != nil { return nil, err } @@ -140,11 +142,11 @@ func (kb dbKeybase) Export(name, oldpass, transferpass string) ([]byte, error) { if transferpass == "" { return key.Bytes(), nil } - res := encryptArmorPrivKey(key, transferpass) - return []byte(res), nil + armorBytes := encryptArmorPrivKey(key, transferpass) + return []byte(armorBytes), nil } -// Import accepts bytes generated by Export along with the same transferpass +// Import accepts bytes generated by Export along with the same transferpass. // If they are valid, it stores the password under the given name with the // new passphrase. func (kb dbKeybase) Import(name, newpass, transferpass string, data []byte) (err error) { @@ -163,7 +165,7 @@ func (kb dbKeybase) Import(name, newpass, transferpass string, data []byte) (err } // Delete removes key forever, but we must present the -// proper passphrase before deleting it (for security) +// proper passphrase before deleting it (for security). func (kb dbKeybase) Delete(name, passphrase string) error { // verify we have the proper password before deleting bs := kb.db.Get(privName(name)) @@ -176,10 +178,10 @@ func (kb dbKeybase) Delete(name, passphrase string) error { return nil } -// Update changes the passphrase with which a already stored key is encoded. +// Update changes the passphrase with which an already stored key is encrypted. // -// oldpass must be the current passphrase used for encoding, newpass will be -// the only valid passphrase from this time forward +// oldpass must be the current passphrase used for encryption, newpass will be +// the only valid passphrase from this time forward. func (kb dbKeybase) Update(name, oldpass, newpass string) error { bs := kb.db.Get(privName(name)) key, err := unarmorDecryptPrivKey(string(bs), oldpass) @@ -187,26 +189,37 @@ func (kb dbKeybase) Update(name, oldpass, newpass string) error { return err } - // we must delete first, as Putting over an existing name returns an error - kb.db.DeleteSync(pubName(name)) - kb.db.DeleteSync(privName(name)) - kb.writeKey(key, name, newpass) + // Generate the public bytes and the encrypted privkey + public := info(name, key) + private := encryptArmorPrivKey(key, newpass) + + // We must delete first, as Putting over an existing name returns an error. + // Must be done atomically with the write or we could lose the key. + batch := kb.db.NewBatch() + batch.Delete(pubName(name)) + batch.Delete(privName(name)) + batch.Set(pubName(name), public.bytes()) + batch.Set(privName(name), []byte(private)) + batch.Write() + return nil } +//--------------------------------------------------------------------------------------- + func (kb dbKeybase) writeKey(priv crypto.PrivKey, name, passphrase string) Info { - // generate the public bytes + // Generate the public bytes and the encrypted privkey public := info(name, priv) - // generate the encrypted privkey private := encryptArmorPrivKey(priv, passphrase) - // write them both + // Write them both kb.db.SetSync(pubName(name), public.bytes()) kb.db.SetSync(privName(name), []byte(private)) return public } +// TODO: use a `type TypeKeyAlgo string` (?) func generate(algo string, secret []byte) (crypto.PrivKey, error) { switch algo { case crypto.NameEd25519: @@ -214,27 +227,13 @@ func generate(algo string, secret []byte) (crypto.PrivKey, error) { case crypto.NameSecp256k1: return crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap(), nil case nano.NameLedgerEd25519: - return nano.NewPrivKeyLedgerEd25519Ed25519() + return nano.NewPrivKeyLedgerEd25519() default: err := errors.Errorf("Cannot generate keys for algorithm: %s", algo) return crypto.PrivKey{}, err } } -func generateByType(typ byte, secret []byte) (crypto.PrivKey, error) { - switch typ { - case crypto.TypeEd25519: - return crypto.GenPrivKeyEd25519FromSecret(secret).Wrap(), nil - case crypto.TypeSecp256k1: - return crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap(), nil - case nano.TypeLedgerEd25519: - return nano.NewPrivKeyLedgerEd25519Ed25519() - default: - err := errors.Errorf("Cannot generate keys for algorithm: %X", typ) - return crypto.PrivKey{}, err - } -} - func pubName(name string) []byte { return []byte(fmt.Sprintf("%s.pub", name)) } diff --git a/keys/keybase_test.go b/keys/keybase_test.go index 72476a02e..12e5205b0 100644 --- a/keys/keybase_test.go +++ b/keys/keybase_test.go @@ -13,6 +13,7 @@ import ( 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" ) @@ -23,7 +24,7 @@ func TestKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) algo := crypto.NameEd25519 @@ -38,7 +39,7 @@ func TestKeyManagement(t *testing.T) { // create some keys _, err = cstore.Get(n1) assert.NotNil(err) - i, _, err := cstore.Create(n1, p1, algo) + _, i, err := cstore.Create(n1, p1, algo) require.Equal(n1, i.Name) require.Nil(err) _, _, err = cstore.Create(n2, p2, algo) @@ -91,7 +92,7 @@ func TestSignVerify(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) algo := crypto.NameSecp256k1 @@ -99,10 +100,10 @@ func TestSignVerify(t *testing.T) { p1, p2 := "1234", "foobar" // create two users and get their info - i1, _, err := cstore.Create(n1, p1, algo) + _, i1, err := cstore.Create(n1, p1, algo) require.Nil(err) - i2, _, err := cstore.Create(n2, p2, algo) + _, i2, err := cstore.Create(n2, p2, algo) require.Nil(err) // let's try to sign some messages @@ -165,13 +166,13 @@ func TestSignWithLedger(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) n := "nano-s" p := "hard2hack" // create a nano user - c, _, err := cstore.Create(n, p, nano.NameLedgerEd25519) + _, c, err := cstore.Create(n, p, nano.NameLedgerEd25519) require.Nil(err, "%+v", err) assert.Equal(c.Name, n) _, ok := c.PubKey.Unwrap().(nano.PubKeyLedgerEd25519) @@ -219,7 +220,7 @@ func TestImportUnencrypted(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) key := crypto.GenPrivKeyEd25519FromSecret(cmn.RandBytes(16)).Wrap() @@ -245,7 +246,7 @@ func TestAdvancedKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) algo := crypto.NameSecp256k1 @@ -288,7 +289,7 @@ func TestSeedPhrase(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) algo := crypto.NameEd25519 @@ -296,7 +297,7 @@ func TestSeedPhrase(t *testing.T) { p1, p2 := "1234", "foobar" // make sure key works with initial password - info, seed, err := cstore.Create(n1, p1, algo) + seed, info, err := cstore.Create(n1, p1, algo) require.Nil(err, "%+v", err) assert.Equal(n1, info.Name) assert.NotEmpty(seed) @@ -308,7 +309,7 @@ func TestSeedPhrase(t *testing.T) { require.NotNil(err) // let us re-create it from the seed-phrase - newInfo, err := cstore.Recover(n2, p2, seed) + newInfo, err := cstore.Recover(n2, p2, algo, seed) require.Nil(err, "%+v", err) assert.Equal(n2, newInfo.Name) assert.Equal(info.Address(), newInfo.Address()) @@ -319,13 +320,13 @@ func ExampleNew() { // Select the encryption and storage for your cryptostore cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) ed := crypto.NameEd25519 sec := crypto.NameSecp256k1 // 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) diff --git a/keys/types.go b/keys/types.go index 541234b37..fdb729e0a 100644 --- a/keys/types.go +++ b/keys/types.go @@ -38,9 +38,9 @@ type Keybase interface { // Sign some bytes Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error) // Create a new keypair - Create(name, passphrase, algo string) (_ Info, seedphrase string, _ error) + Create(name, passphrase, algo string) (seedphrase string, _ Info, _ error) // Recover takes a seedphrase and loads in the key - Recover(name, passphrase, seedphrase string) (Info, error) + Recover(name, passphrase, algo, seedphrase string) (Info, error) List() ([]Info, error) Get(name string) (Info, error) Update(name, oldpass, newpass string) error diff --git a/keys/ecc.go b/keys/words/ecc.go similarity index 99% rename from keys/ecc.go rename to keys/words/ecc.go index c1ac258fe..c511ad6e4 100644 --- a/keys/ecc.go +++ b/keys/words/ecc.go @@ -1,4 +1,4 @@ -package keys +package words import ( "encoding/binary" diff --git a/keys/ecc_test.go b/keys/words/ecc_test.go similarity index 98% rename from keys/ecc_test.go rename to keys/words/ecc_test.go index 6d3e3bec8..9e1772b9f 100644 --- a/keys/ecc_test.go +++ b/keys/words/ecc_test.go @@ -1,4 +1,4 @@ -package keys +package words import ( "testing" diff --git a/keys/wordcodec.go b/keys/words/wordcodec.go similarity index 98% rename from keys/wordcodec.go rename to keys/words/wordcodec.go index c551e54ce..fbf32160f 100644 --- a/keys/wordcodec.go +++ b/keys/words/wordcodec.go @@ -1,4 +1,4 @@ -package keys +package words import ( "math/big" @@ -6,7 +6,7 @@ import ( "github.com/pkg/errors" - "github.com/tendermint/go-crypto/keys/wordlist" + "github.com/tendermint/go-crypto/keys/words/wordlist" ) const BankSize = 2048 diff --git a/keys/wordcodec_test.go b/keys/words/wordcodec_test.go similarity index 99% rename from keys/wordcodec_test.go rename to keys/words/wordcodec_test.go index f79ebcad0..367e3799a 100644 --- a/keys/wordcodec_test.go +++ b/keys/words/wordcodec_test.go @@ -1,4 +1,4 @@ -package keys +package words import ( "testing" diff --git a/keys/wordcodecbench_test.go b/keys/words/wordcodecbench_test.go similarity index 98% rename from keys/wordcodecbench_test.go rename to keys/words/wordcodecbench_test.go index e100a443a..04417a936 100644 --- a/keys/wordcodecbench_test.go +++ b/keys/words/wordcodecbench_test.go @@ -1,4 +1,4 @@ -package keys +package words import ( "testing" diff --git a/keys/wordlist/chinese_simplified.txt b/keys/words/wordlist/chinese_simplified.txt similarity index 100% rename from keys/wordlist/chinese_simplified.txt rename to keys/words/wordlist/chinese_simplified.txt diff --git a/keys/wordlist/english.txt b/keys/words/wordlist/english.txt similarity index 100% rename from keys/wordlist/english.txt rename to keys/words/wordlist/english.txt diff --git a/keys/wordlist/japanese.txt b/keys/words/wordlist/japanese.txt similarity index 100% rename from keys/wordlist/japanese.txt rename to keys/words/wordlist/japanese.txt diff --git a/keys/wordlist/spanish.txt b/keys/words/wordlist/spanish.txt similarity index 100% rename from keys/wordlist/spanish.txt rename to keys/words/wordlist/spanish.txt diff --git a/keys/wordlist/wordlist.go b/keys/words/wordlist/wordlist.go similarity index 100% rename from keys/wordlist/wordlist.go rename to keys/words/wordlist/wordlist.go diff --git a/nano/keys.go b/nano/keys.go index a6d3ea8e4..b50efd7ec 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -33,21 +33,21 @@ func getLedger() (*ledger.Ledger, error) { return device, err } -func signLedger(device *ledger.Ledger, msg []byte) (pk crypto.PubKey, sig crypto.Signature, err error) { +func signLedger(device *ledger.Ledger, msg []byte) (pub crypto.PubKey, sig crypto.Signature, err error) { var resp []byte packets := generateSignRequests(msg) for _, pack := range packets { resp, err = device.Exchange(pack, Timeout) if err != nil { - return pk, sig, err + return pub, sig, err } } // the last call is the result we want and needs to be parsed key, bsig, err := parseDigest(resp) if err != nil { - return pk, sig, err + return pub, sig, err } var b [32]byte @@ -64,9 +64,9 @@ type PrivKeyLedgerEd25519 struct { CachedPubKey crypto.PubKey } -// NewPrivKeyLedgerEd25519Ed25519 will generate a new key and store the +// NewPrivKeyLedgerEd25519 will generate a new key and store the // public key for later use. -func NewPrivKeyLedgerEd25519Ed25519() (crypto.PrivKey, error) { +func NewPrivKeyLedgerEd25519() (crypto.PrivKey, error) { var pk PrivKeyLedgerEd25519 // getPubKey will cache the pubkey for later use, // this allows us to return an error early if the ledger @@ -94,13 +94,13 @@ func (pk *PrivKeyLedgerEd25519) ValidateKey() error { // AssertIsPrivKeyInner fulfils PrivKey Interface func (pk *PrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} -// Bytes fulfils pk Interface - stores the cached pubkey so we can verify +// Bytes fulfils PrivKey Interface - but it stores the cached pubkey so we can verify // the same key when we reconnect to a ledger func (pk *PrivKeyLedgerEd25519) Bytes() []byte { return wire.BinaryBytes(pk.Wrap()) } -// Sign calls the ledger and stores the pk for future use +// Sign calls the ledger and stores the PubKey for future use // // XXX/TODO: panics if there is an error communicating with the ledger. // diff --git a/nano/keys_test.go b/nano/keys_test.go index 2e5142e30..fda096e29 100644 --- a/nano/keys_test.go +++ b/nano/keys_test.go @@ -83,7 +83,7 @@ func TestRealLedger(t *testing.T) { } msg := []byte("kuhehfeohg") - priv, err := NewPrivKeyLedgerEd25519Ed25519() + priv, err := NewPrivKeyLedgerEd25519() require.Nil(err, "%+v", err) pub := priv.PubKey() sig := priv.Sign(msg) @@ -123,7 +123,7 @@ func TestRealLedgerErrorHandling(t *testing.T) { // first, try to generate a key, must return an error // (no panic) - _, err := NewPrivKeyLedgerEd25519Ed25519() + _, err := NewPrivKeyLedgerEd25519() require.Error(err) led := PrivKeyLedgerEd25519{} // empty