Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

bump btcd for security fix #1716

Merged
merged 5 commits into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crypto/hd/algorithm.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
package hd

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

"github.com/ethereum/go-ethereum/accounts"
Expand Down
12 changes: 5 additions & 7 deletions crypto/hd/algorithm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (

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

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

amino "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
Expand Down Expand Up @@ -75,11 +73,11 @@ func TestKeyring(t *testing.T) {
addr := common.BytesToAddress(privkey.PubKey().Address().Bytes())

os.Setenv(hdWalletFixEnv, "true")
wallet, err := hdwallet.NewFromMnemonic(mnemonic)
wallet, err := NewFromMnemonic(mnemonic)
os.Setenv(hdWalletFixEnv, "")
require.NoError(t, err)

path := hdwallet.MustParseDerivationPath(hdPath)
path := MustParseDerivationPath(hdPath)

account, err := wallet.Derive(path, false)
require.NoError(t, err)
Expand All @@ -102,14 +100,14 @@ func TestDerivation(t *testing.T) {

require.False(t, privkey.Equals(badPrivKey))

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

path := hdwallet.MustParseDerivationPath(ethermint.BIP44HDPath)
path := MustParseDerivationPath(ethermint.BIP44HDPath)
account, err := wallet.Derive(path, false)
require.NoError(t, err)

badPath := hdwallet.MustParseDerivationPath("44'/60'/0'/0/0")
badPath := MustParseDerivationPath("44'/60'/0'/0/0")
badAccount, err := wallet.Derive(badPath, false)
require.NoError(t, err)

Expand Down
182 changes: 182 additions & 0 deletions crypto/hd/utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// NOTE: This code is being used as test helper functions.
package hd

import (
"crypto/ecdsa"
"errors"
"os"
"sync"

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

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

const issue179FixEnvar = "GO_ETHEREUM_HDWALLET_FIX_ISSUE_179"

// Wallet is the underlying wallet struct.
type Wallet struct {
mnemonic string
masterKey *hdkeychain.ExtendedKey
seed []byte
paths map[common.Address]accounts.DerivationPath
accounts []accounts.Account
stateLock sync.RWMutex
fixIssue172 bool
}

// NewFromMnemonic returns a new wallet from a BIP-39 mnemonic.
func NewFromMnemonic(mnemonic string) (*Wallet, error) {
if mnemonic == "" {
return nil, errors.New("mnemonic is required")
}

if !bip39.IsMnemonicValid(mnemonic) {
return nil, errors.New("mnemonic is invalid")
}

seed, err := NewSeedFromMnemonic(mnemonic)
if err != nil {
return nil, err
}

wallet, err := newWallet(seed)
if err != nil {
return nil, err
}
wallet.mnemonic = mnemonic

return wallet, nil
}

// NewSeedFromMnemonic returns a BIP-39 seed based on a BIP-39 mnemonic.
func NewSeedFromMnemonic(mnemonic string) ([]byte, error) {
if mnemonic == "" {
return nil, errors.New("mnemonic is required")
}

return bip39.NewSeedWithErrorChecking(mnemonic, "")
}

func newWallet(seed []byte) (*Wallet, error) {
masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
if err != nil {
return nil, err
}

return &Wallet{
masterKey: masterKey,
seed: seed,
accounts: []accounts.Account{},
paths: map[common.Address]accounts.DerivationPath{},
fixIssue172: false || len(os.Getenv(issue179FixEnvar)) > 0,
}, nil
}

// Derive implements accounts.Wallet, deriving a new account at the specific
// derivation path. If pin is set to true, the account will be added to the list
// of tracked accounts.
func (w *Wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) {
// Try to derive the actual account and update its URL if successful
w.stateLock.RLock() // Avoid device disappearing during derivation

address, err := w.deriveAddress(path)

w.stateLock.RUnlock()

// If an error occurred or no pinning was requested, return
if err != nil {
return accounts.Account{}, err
}

account := accounts.Account{
Address: address,
URL: accounts.URL{
Scheme: "",
Path: path.String(),
},
}

if !pin {
return account, nil
}

// Pinning needs to modify the state
w.stateLock.Lock()
defer w.stateLock.Unlock()

if _, ok := w.paths[address]; !ok {
w.accounts = append(w.accounts, account)
w.paths[address] = path
}

return account, nil
}

// MustParseDerivationPath parses the derivation path in string format into
// []uint32 but will panic if it can't parse it.
func MustParseDerivationPath(path string) accounts.DerivationPath {
parsed, err := accounts.ParseDerivationPath(path)
if err != nil {
panic(err)
}

return parsed
}

// DerivePrivateKey derives the private key of the derivation path.
func (w *Wallet) derivePrivateKey(path accounts.DerivationPath) (*ecdsa.PrivateKey, error) {
var err error
key := w.masterKey
for _, n := range path {
if w.fixIssue172 && key.IsAffectedByIssue172() {
key, err = key.Derive(n)
} else {
//lint:ignore SA1019 this is used for testing only
//nolint:all
key, err = key.DeriveNonStandard(n)
}
if err != nil {
return nil, err
}
}

privateKey, err := key.ECPrivKey()
privateKeyECDSA := privateKey.ToECDSA()
if err != nil {
return nil, err
}

return privateKeyECDSA, nil
}

// derivePublicKey derives the public key of the derivation path.
func (w *Wallet) derivePublicKey(path accounts.DerivationPath) (*ecdsa.PublicKey, error) {
privateKeyECDSA, err := w.derivePrivateKey(path)
if err != nil {
return nil, err
}

publicKey := privateKeyECDSA.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
return nil, errors.New("failed to get public key")
}

return publicKeyECDSA, nil
}

// DeriveAddress derives the account address of the derivation path.
func (w *Wallet) deriveAddress(path accounts.DerivationPath) (common.Address, error) {
publicKeyECDSA, err := w.derivePublicKey(path)
if err != nil {
return common.Address{}, err
}

address := crypto.PubkeyToAddress(*publicKeyECDSA)
return address, nil
}
24 changes: 13 additions & 11 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ require (
cosmossdk.io/errors v1.0.0-beta.7
cosmossdk.io/math v1.0.0-rc.0
github.com/armon/go-metrics v0.4.1
github.com/btcsuite/btcd v0.22.2
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
github.com/btcsuite/btcd v0.23.4
github.com/btcsuite/btcd/btcutil v1.1.3
github.com/cosmos/cosmos-proto v1.0.0-beta.3
github.com/cosmos/cosmos-sdk v0.46.8
github.com/cosmos/cosmos-sdk v0.46.11
github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/gogoproto v1.4.6
github.com/cosmos/ibc-go/v6 v6.1.0
Expand All @@ -22,7 +22,6 @@ require (
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/holiman/uint256 v1.2.1
github.com/improbable-eng/grpc-web v0.15.0
github.com/miguelmota/go-ethereum-hdwallet v0.1.1
github.com/onsi/ginkgo/v2 v2.9.1
github.com/onsi/gomega v1.27.4
github.com/pkg/errors v0.9.1
Expand All @@ -33,7 +32,7 @@ require (
github.com/spf13/viper v1.15.0
github.com/status-im/keycard-go v0.2.0
github.com/stretchr/testify v1.8.2
github.com/tendermint/tendermint v0.34.24
github.com/tendermint/tendermint v0.34.27
github.com/tendermint/tm-db v0.6.7
github.com/tyler-smith/go-bip39 v1.1.0
golang.org/x/net v0.8.0
Expand Down Expand Up @@ -67,10 +66,11 @@ require (
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
github.com/cockroachdb/apd/v2 v2.0.2 // indirect
github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect
github.com/cometbft/cometbft-db v0.7.0 // indirect
github.com/confio/ics23/go v0.9.0 // indirect
github.com/cosmos/btcutil v1.0.5 // indirect
github.com/cosmos/gorocksdb v1.2.0 // indirect
github.com/cosmos/iavl v0.19.4 // indirect
github.com/cosmos/iavl v0.19.5 // indirect
github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect
github.com/creachadair/taskgroup v0.3.2 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
Expand Down Expand Up @@ -101,7 +101,7 @@ require (
github.com/golang/glog v1.0.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/orderedcode v0.0.1 // indirect
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
Expand Down Expand Up @@ -147,9 +147,9 @@ require (
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.12.2 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.34.0 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/prometheus/tsdb v0.7.1 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
Expand All @@ -164,6 +164,7 @@ require (
github.com/stretchr/objx v0.5.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
github.com/tendermint/go-amino v0.16.0 // indirect
github.com/tidwall/btree v1.5.0 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
Expand All @@ -173,7 +174,7 @@ require (
github.com/zondax/ledger-go v0.14.1 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.3.0 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/exp v0.0.0-20230131160201-f062dba9d201 // indirect
golang.org/x/oauth2 v0.4.0 // indirect
golang.org/x/sync v0.1.0 // indirect
Expand All @@ -199,4 +200,5 @@ replace (
github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0
// use cosmos flavored protobufs
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27
)
Loading