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

Commit 592eca9

Browse files
keys: fix privkey derivation (#554)
* keys: fix privkey derivation * changelog * add DeriveSecp256k1 test Co-authored-by: araskachoi <[email protected]>
1 parent 7f648d2 commit 592eca9

File tree

5 files changed

+92
-19
lines changed

5 files changed

+92
-19
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
3939

4040
### Bug fixes
4141

42-
* (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.
42+
* (keys) [\#554](https://github.com/ChainSafe/ethermint/pull/554) Fix private key derivation.
43+
* (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.
4344

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

crypto/algorithm.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import (
55

66
"github.com/pkg/errors"
77

8-
"crypto/hmac"
9-
"crypto/sha512"
10-
8+
"github.com/btcsuite/btcd/chaincfg"
9+
"github.com/btcsuite/btcutil/hdkeychain"
1110
"github.com/tyler-smith/go-bip39"
1211

12+
ethaccounts "github.com/ethereum/go-ethereum/accounts"
1313
ethcrypto "github.com/ethereum/go-ethereum/crypto"
1414

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

61-
func DeriveSecp256k1(mnemonic, bip39Passphrase, _ string) ([]byte, error) {
61+
// DeriveSecp256k1 derives and returns the eth_secp256k1 private key for the given mnemonic and HD path.
62+
func DeriveSecp256k1(mnemonic, bip39Passphrase, path string) ([]byte, error) {
63+
hdpath, err := ethaccounts.ParseDerivationPath(path)
64+
if err != nil {
65+
return nil, err
66+
}
67+
6268
seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase)
6369
if err != nil {
6470
return nil, err
6571
}
6672

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

74-
seed = mac.Sum(nil)
78+
key := masterKey
79+
for _, n := range hdpath {
80+
key, err = key.Child(n)
81+
if err != nil {
82+
return nil, err
83+
}
84+
}
7585

76-
priv, err := ethcrypto.ToECDSA(seed[:32])
86+
privateKey, err := key.ECPrivKey()
7787
if err != nil {
7888
return nil, err
7989
}
8090

81-
derivedKey := PrivKeySecp256k1(ethcrypto.FromECDSA(priv))
82-
91+
privateKeyECDSA := privateKey.ToECDSA()
92+
derivedKey := PrivKeySecp256k1(ethcrypto.FromECDSA(privateKeyECDSA))
8393
return derivedKey, nil
8494
}

crypto/algorithm_test.go

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@ import (
66

77
"github.com/stretchr/testify/require"
88

9+
"github.com/ethereum/go-ethereum/common"
910
ethcrypto "github.com/ethereum/go-ethereum/crypto"
1011

12+
hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
13+
1114
"github.com/cosmos/cosmos-sdk/crypto/keys"
1215
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
1316
"github.com/cosmos/cosmos-sdk/tests"
14-
sdk "github.com/cosmos/cosmos-sdk/types"
17+
18+
ethermint "github.com/cosmos/ethermint/types"
1519
)
1620

1721
func TestEthermintKeygenFunc(t *testing.T) {
@@ -75,25 +79,45 @@ func TestKeyring(t *testing.T) {
7579
require.Nil(t, info)
7680

7781
mockIn.Reset("password\npassword\n")
78-
info, mnemonic, err := kr.CreateMnemonic("foo", keys.English, sdk.FullFundraiserPath, EthSecp256k1)
82+
info, mnemonic, err := kr.CreateMnemonic("foo", keys.English, ethermint.BIP44HDPath, EthSecp256k1)
7983
require.NoError(t, err)
8084
require.NotEmpty(t, mnemonic)
8185
require.Equal(t, "foo", info.GetName())
8286
require.Equal(t, "local", info.GetType().String())
8387
require.Equal(t, EthSecp256k1, info.GetAlgo())
8488

85-
params := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
89+
params := *hd.NewFundraiserParams(0, ethermint.Bip44CoinType, 0)
8690
hdPath := params.String()
8791

88-
bz, err := DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, EthSecp256k1)
92+
bz, err := DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, keys.Secp256k1)
8993
require.NoError(t, err)
9094
require.NotEmpty(t, bz)
9195

92-
bz, err = DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, keys.Secp256k1)
96+
bz, err = DeriveSecp256k1(mnemonic, keys.DefaultBIP39Passphrase, hdPath)
9397
require.NoError(t, err)
9498
require.NotEmpty(t, bz)
9599

96100
bz, err = DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, keys.SigningAlgo(""))
97101
require.Error(t, err)
98102
require.Empty(t, bz)
103+
104+
bz, err = DeriveSecp256k1(mnemonic, keys.DefaultBIP39Passphrase, "/wrong/hdPath")
105+
require.Error(t, err)
106+
require.Empty(t, bz)
107+
108+
bz, err = DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, EthSecp256k1)
109+
require.NoError(t, err)
110+
require.NotEmpty(t, bz)
111+
112+
privkey := PrivKeySecp256k1(bz)
113+
addr := common.BytesToAddress(privkey.PubKey().Address().Bytes())
114+
115+
wallet, err := hdwallet.NewFromMnemonic(mnemonic)
116+
require.NoError(t, err)
117+
118+
path := hdwallet.MustParseDerivationPath(hdPath)
119+
120+
account, err := wallet.Derive(path, false)
121+
require.NoError(t, err)
122+
require.Equal(t, addr.String(), account.Address.String())
99123
}

go.mod

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ module github.com/cosmos/ethermint
33
go 1.14
44

55
require (
6-
github.com/allegro/bigcache v1.2.1 // indirect
76
github.com/aristanetworks/goarista v0.0.0-20200331225509-2cc472e8fbd6 // indirect
7+
github.com/btcsuite/btcd v0.20.1-beta
8+
github.com/btcsuite/btcutil v1.0.2
89
github.com/cespare/cp v1.1.1 // indirect
910
github.com/cosmos/cosmos-sdk v0.39.1
1011
github.com/deckarep/golang-set v1.7.1 // indirect
@@ -13,9 +14,9 @@ require (
1314
github.com/gorilla/mux v1.8.0
1415
github.com/gorilla/websocket v1.4.2
1516
github.com/mattn/go-colorable v0.1.7 // indirect
17+
github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20200123000308-a60dcd172b4c
1618
github.com/pkg/errors v0.9.1
1719
github.com/prometheus/tsdb v0.9.1 // indirect
18-
github.com/rjeczalik/notify v0.9.2 // indirect
1920
github.com/spf13/afero v1.2.2 // indirect
2021
github.com/spf13/cobra v1.0.0
2122
github.com/spf13/viper v1.7.1

0 commit comments

Comments
 (0)