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

Commit

Permalink
keys: fix privkey derivation (#554)
Browse files Browse the repository at this point in the history
* keys: fix privkey derivation

* changelog

* add DeriveSecp256k1 test

Co-authored-by: araskachoi <choidanielw@gmail.com>
  • Loading branch information
fedekunze and araskachoi committed Sep 29, 2020
1 parent 7f648d2 commit 592eca9
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 19 deletions.
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) {
// 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
}
34 changes: 29 additions & 5 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,45 @@ 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)
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.Secp256k1)
bz, err = DeriveSecp256k1(mnemonic, keys.DefaultBIP39Passphrase, hdPath)
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 = DeriveSecp256k1(mnemonic, keys.DefaultBIP39Passphrase, "/wrong/hdPath")
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)
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
Loading

0 comments on commit 592eca9

Please sign in to comment.