laconicd/crypto/hd/algorithm.go

106 lines
2.8 KiB
Go
Raw Normal View History

package hd
import (
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil/hdkeychain"
2021-04-17 10:00:07 +00:00
bip39 "github.com/tyler-smith/go-bip39"
ethaccounts "github.com/ethereum/go-ethereum/accounts"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
2021-04-17 10:00:07 +00:00
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
)
const (
2021-04-17 10:00:07 +00:00
// EthSecp256k1Type defines the ECDSA secp256k1 used on Ethereum
EthSecp256k1Type = hd.PubKeyType(ethsecp256k1.KeyType)
)
2021-04-17 10:00:07 +00:00
var (
// SupportedAlgorithms defines the list of signing algorithms used on Ethermint:
// - eth_secp256k1 (Ethereum)
// - secp256k1 (Tendermint)
SupportedAlgorithms = keyring.SigningAlgoList{EthSecp256k1, hd.Secp256k1}
// SupportedAlgorithmsLedger defines the list of signing algorithms used on Ethermint for the Ledger device:
// - eth_secp256k1 (Ethereum)
// - secp256k1 (Tendermint)
SupportedAlgorithmsLedger = keyring.SigningAlgoList{EthSecp256k1, hd.Secp256k1}
)
2021-04-17 10:00:07 +00:00
// EthSecp256k1Option defines a function keys options for the ethereum Secp256k1 curve.
// It supports eth_secp256k1 and secp256k1 keys for accounts.
func EthSecp256k1Option() keyring.Option {
return func(options *keyring.Options) {
options.SupportedAlgos = SupportedAlgorithms
options.SupportedAlgosLedger = SupportedAlgorithmsLedger
}
2021-04-17 10:00:07 +00:00
}
2021-04-17 10:00:07 +00:00
var (
_ keyring.SignatureAlgo = EthSecp256k1
2021-04-17 10:00:07 +00:00
// EthSecp256k1 uses the Bitcoin secp256k1 ECDSA parameters.
EthSecp256k1 = ethSecp256k1Algo{}
)
type ethSecp256k1Algo struct {
}
2021-04-17 10:00:07 +00:00
// Name returns eth_secp256k1
func (s ethSecp256k1Algo) Name() hd.PubKeyType {
return EthSecp256k1Type
}
2021-04-17 10:00:07 +00:00
// Derive derives and returns the eth_secp256k1 private key for the given mnemonic and HD path.
func (s ethSecp256k1Algo) Derive() hd.DeriveFn {
return func(mnemonic string, bip39Passphrase, path string) ([]byte, error) {
hdpath, err := ethaccounts.ParseDerivationPath(path)
if err != nil {
return nil, err
}
2021-04-17 10:00:07 +00:00
seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase)
if err != nil {
return nil, err
}
2021-04-17 10:00:07 +00:00
masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
if err != nil {
return nil, err
}
2021-04-17 10:00:07 +00:00
key := masterKey
for _, n := range hdpath {
key, err = key.Derive(n)
2021-04-17 10:00:07 +00:00
if err != nil {
return nil, err
}
}
privateKey, err := key.ECPrivKey()
if err != nil {
return nil, err
}
privateKeyECDSA := privateKey.ToECDSA()
derivedKey := ethcrypto.FromECDSA(privateKeyECDSA)
return derivedKey, nil
}
2021-04-17 10:00:07 +00:00
}
// Generate generates a eth_secp256k1 private key from the given bytes.
func (s ethSecp256k1Algo) Generate() hd.GenerateFn {
return func(bz []byte) cryptotypes.PrivKey {
var bzArr = make([]byte, ethsecp256k1.PrivKeySize)
copy(bzArr, bz)
2021-04-17 10:00:07 +00:00
return &ethsecp256k1.PrivKey{Key: bzArr}
}
}