-
Notifications
You must be signed in to change notification settings - Fork 0
/
algorithm.go
126 lines (106 loc) · 3.89 KB
/
algorithm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright 2022 Hekas Foundation
// This file is part of the Hekas Network packages.
//
// Hekas is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The Hekas packages are distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the Hekas packages. If not, see https://github.com/hekas-network/hekas/blob/main/LICENSE
package hd
import (
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil/hdkeychain"
bip39 "github.com/tyler-smith/go-bip39"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/crypto"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/hekas-network/hekas/crypto/ethsecp256k1"
)
const (
// EthSecp256k1Type defines the ECDSA secp256k1 used on Ethereum
EthSecp256k1Type = hd.PubKeyType(ethsecp256k1.KeyType)
)
var (
// SupportedAlgorithms defines the list of signing algorithms used on Hekas:
// - eth_secp256k1 (Ethereum)
// - secp256k1 (Tendermint)
SupportedAlgorithms = keyring.SigningAlgoList{EthSecp256k1, hd.Secp256k1}
// SupportedAlgorithmsLedger defines the list of signing algorithms used on Hekas for the Ledger device:
// - eth_secp256k1 (Ethereum)
// - secp256k1 (Tendermint)
SupportedAlgorithmsLedger = keyring.SigningAlgoList{EthSecp256k1, hd.Secp256k1}
)
// 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
}
}
var (
_ keyring.SignatureAlgo = EthSecp256k1
// EthSecp256k1 uses the Bitcoin secp256k1 ECDSA parameters.
EthSecp256k1 = ethSecp256k1Algo{}
)
type ethSecp256k1Algo struct{}
// Name returns eth_secp256k1
func (s ethSecp256k1Algo) Name() hd.PubKeyType {
return EthSecp256k1Type
}
// 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, bip39Passphrase, path string) ([]byte, error) {
hdpath, err := accounts.ParseDerivationPath(path)
if err != nil {
return nil, err
}
seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase)
if err != nil {
return nil, err
}
// create a BTC-utils hd-derivation key chain
masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
if err != nil {
return nil, err
}
key := masterKey
for _, n := range hdpath {
key, err = key.Derive(n)
if err != nil {
return nil, err
}
}
// btc-utils representation of a secp256k1 private key
privateKey, err := key.ECPrivKey()
if err != nil {
return nil, err
}
// cast private key to a convertible form (single scalar field element of secp256k1)
// and then load into ethcrypto private key format.
// TODO: add links to godocs of the two methods or implementations of them, to compare equivalency
privateKeyECDSA := privateKey.ToECDSA()
derivedKey := crypto.FromECDSA(privateKeyECDSA)
return derivedKey, nil
}
}
// Generate generates a eth_secp256k1 private key from the given bytes.
func (s ethSecp256k1Algo) Generate() hd.GenerateFn {
return func(bz []byte) cryptotypes.PrivKey {
bzArr := make([]byte, ethsecp256k1.PrivKeySize)
copy(bzArr, bz)
// TODO: modulo P
return ðsecp256k1.PrivKey{
Key: bzArr,
}
}
}