Skip to content
This repository has been archived by the owner on Nov 30, 2021. It is now read-only.

keys: fix privkey derivation #554

Merged
merged 3 commits into from
Sep 29, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Bug fixes

* (app/ante) [\#550](https://github.com/ChainSafe/ethermint/pull/550) Update ante handler nonce verification to accept any nonce greater than or equal to the expected nonce to allow to successive transactions.
* (keys) [\#554](https://github.com/ChainSafe/ethermint/pull/554) Fix private key derivation.
* (app/ante) [\#550](https://github.com/ChainSafe/ethermint/pull/550) Update ante handler nonce verification to accept any nonce greater than or equal to the expected nonce to allow to successive transactions.

## [v0.2.0] - 2020-09-24

Expand Down
32 changes: 21 additions & 11 deletions crypto/algorithm.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import (

"github.com/pkg/errors"

"crypto/hmac"
"crypto/sha512"

"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil/hdkeychain"
"github.com/tyler-smith/go-bip39"

ethaccounts "github.com/ethereum/go-ethereum/accounts"
ethcrypto "github.com/ethereum/go-ethereum/crypto"

tmcrypto "github.com/tendermint/tendermint/crypto"
Expand Down Expand Up @@ -58,27 +58,37 @@ func EthermintKeygenFunc(bz []byte, algo keys.SigningAlgo) (tmcrypto.PrivKey, er
return PrivKeySecp256k1(bz), nil
}

func DeriveSecp256k1(mnemonic, bip39Passphrase, _ string) ([]byte, error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hdpath wasn't being used to derive the key

// DeriveSecp256k1 derives and returns the eth_secp256k1 private key for the given mnemonic and HD path.
func DeriveSecp256k1(mnemonic, bip39Passphrase, path string) ([]byte, error) {
hdpath, err := ethaccounts.ParseDerivationPath(path)
if err != nil {
return nil, err
}

seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase)
if err != nil {
return nil, err
}

// HMAC the seed to produce the private key and chain code
mac := hmac.New(sha512.New, []byte("Bitcoin seed"))
_, err = mac.Write(seed)
masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
if err != nil {
return nil, err
}

seed = mac.Sum(nil)
key := masterKey
for _, n := range hdpath {
key, err = key.Child(n)
if err != nil {
return nil, err
}
}

priv, err := ethcrypto.ToECDSA(seed[:32])
privateKey, err := key.ECPrivKey()
if err != nil {
return nil, err
}

derivedKey := PrivKeySecp256k1(ethcrypto.FromECDSA(priv))

privateKeyECDSA := privateKey.ToECDSA()
derivedKey := PrivKeySecp256k1(ethcrypto.FromECDSA(privateKeyECDSA))
return derivedKey, nil
}
32 changes: 24 additions & 8 deletions crypto/algorithm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ import (

"github.com/stretchr/testify/require"

"github.com/ethereum/go-ethereum/common"
ethcrypto "github.com/ethereum/go-ethereum/crypto"

hdwallet "github.com/miguelmota/go-ethereum-hdwallet"

"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
"github.com/cosmos/cosmos-sdk/tests"
sdk "github.com/cosmos/cosmos-sdk/types"

ethermint "github.com/cosmos/ethermint/types"
)

func TestEthermintKeygenFunc(t *testing.T) {
Expand Down Expand Up @@ -75,25 +79,37 @@ func TestKeyring(t *testing.T) {
require.Nil(t, info)

mockIn.Reset("password\npassword\n")
info, mnemonic, err := kr.CreateMnemonic("foo", keys.English, sdk.FullFundraiserPath, EthSecp256k1)
info, mnemonic, err := kr.CreateMnemonic("foo", keys.English, ethermint.BIP44HDPath, EthSecp256k1)
require.NoError(t, err)
require.NotEmpty(t, mnemonic)
require.Equal(t, "foo", info.GetName())
require.Equal(t, "local", info.GetType().String())
require.Equal(t, EthSecp256k1, info.GetAlgo())

params := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
params := *hd.NewFundraiserParams(0, ethermint.Bip44CoinType, 0)
hdPath := params.String()

bz, err := DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, EthSecp256k1)
require.NoError(t, err)
require.NotEmpty(t, bz)

bz, err = DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, keys.Secp256k1)
bz, err := DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, keys.Secp256k1)
require.NoError(t, err)
require.NotEmpty(t, bz)

bz, err = DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, keys.SigningAlgo(""))
require.Error(t, err)
require.Empty(t, bz)

bz, err = DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, EthSecp256k1)
require.NoError(t, err)
require.NotEmpty(t, bz)

privkey := PrivKeySecp256k1(bz)
addr := common.BytesToAddress(privkey.PubKey().Address().Bytes())

wallet, err := hdwallet.NewFromMnemonic(mnemonic)
require.NoError(t, err)

path := hdwallet.MustParseDerivationPath(hdPath)

account, err := wallet.Derive(path, false)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used this library to test the correctness with ethereum

require.NoError(t, err)
require.Equal(t, addr.String(), account.Address.String())
}
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ module github.com/cosmos/ethermint
go 1.14

require (
github.com/allegro/bigcache v1.2.1 // indirect
github.com/aristanetworks/goarista v0.0.0-20200331225509-2cc472e8fbd6 // indirect
github.com/btcsuite/btcd v0.20.1-beta
github.com/btcsuite/btcutil v1.0.2
github.com/cespare/cp v1.1.1 // indirect
github.com/cosmos/cosmos-sdk v0.39.1
github.com/deckarep/golang-set v1.7.1 // indirect
Expand All @@ -13,9 +14,9 @@ require (
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.4.2
github.com/mattn/go-colorable v0.1.7 // indirect
github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20200123000308-a60dcd172b4c
github.com/pkg/errors v0.9.1
github.com/prometheus/tsdb v0.9.1 // indirect
github.com/rjeczalik/notify v0.9.2 // indirect
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/cobra v1.0.0
github.com/spf13/viper v1.7.1
Expand Down