Skip to content

Commit

Permalink
新增RawKey 给出原始私钥/公钥
Browse files Browse the repository at this point in the history
  • Loading branch information
孙显松 committed Nov 20, 2020
1 parent 797c47d commit 8cf1f86
Show file tree
Hide file tree
Showing 11 changed files with 173 additions and 27 deletions.
3 changes: 3 additions & 0 deletions cmd/cli/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build:
GOOS=windows GOARCH=amd64 go build -o wcli.exe
go build -o wcli
49 changes: 49 additions & 0 deletions cmd/cli/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package main

import (
"flag"
"fmt"

"github.com/dabankio/wallet-core/bip44"
"github.com/dabankio/wallet-core/wallet"
)

var pass string
var mne string

func init() {
flag.StringVar(&pass, "pass", "", "-pass xxx")
flag.StringVar(&mne, "mne", "", "-mne xxx")
flag.Parse()
}

func main() {
const s = "BBC"

options := &wallet.WalletOptions{}
options.Add(wallet.WithPathFormat(bip44.FullPathFormat)) //m/44'/%d'/0'/0/0, 确保兼容imToken
options.Add(wallet.WithPassword(pass)) //确保兼容imToken
options.Add(wallet.WithShareAccountWithParentChain(true)) //USDT BTC共用地址
options.Add(wallet.WithFlag(wallet.FlagBBCUseStandardBip44ID)) //BBC使用标准bip44 ID
options.Add(wallet.WithFlag(wallet.FlagMKFUseBBCBip44ID)) //MKF 和BBC共用地址

w, err := wallet.BuildWalletFromMnemonic(mne, true, options)
pe(err)

privk, err := w.DerivePrivateKey(s)
pe(err)
pubk, err := w.DerivePublicKey(s)
pe(err)
address, err := w.DeriveAddress(s)
pe(err)

fmt.Println("addr", address)
fmt.Println("pubk", pubk)
fmt.Println("prvk", privk)
}

func pe(e error) {
if e != nil {
panic(e)
}
}
4 changes: 1 addition & 3 deletions core/bbc/internal/bip44.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ func init() {
}

const (
ed25519SeedSize = 32

// RecommendedSeedLen is the recommended length in bytes for a seed
// to a master node.
RecommendedSeedLen = 32 // 256 bits
Expand Down Expand Up @@ -279,7 +277,7 @@ func (k *ExtendedKey) Child(i uint32) (*ExtendedKey, error) {
ilNum.Mod(ilNum, ed25519L)
childKey = ilNum.Bytes()

if len(childKey) != ed25519SeedSize {
if len(childKey) != ed25519.SeedSize {
_s := blake2b.Sum256(childKey)
childKey = _s[:]
}
Expand Down
17 changes: 17 additions & 0 deletions core/bbc/internal/coin.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package internal

import (
"crypto/ed25519"

"github.com/dabankio/gobbc"
"github.com/dabankio/wallet-core/bip44"
"github.com/dabankio/wallet-core/core"
Expand Down Expand Up @@ -143,6 +145,21 @@ func (c *Wallet) Sign(msg, privateKey string) (string, error) {
return c.SignTemplate(msg, "", privateKey)
}

// RawKey 32+32
func (c *Wallet) RawKey() ([]byte, error) {
child, err := c.derive()
if err != nil {
return nil, err
}
b := make([]byte, 0)
b = core.PaddedAppend(ed25519.SeedSize, b, child.key)
pubk, err := gobbc.Seed2pubk(child.key)
if err != nil {
return nil, err
}
return append(b, pubk...), nil
}

// VerifySignature verifies rawTx's signature is intact
func (c *Wallet) VerifySignature(pubKey, msg, signature string) error {
return errors.New("verify signature not supported for BBC currently")
Expand Down
12 changes: 12 additions & 0 deletions core/btc/internal/btc.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,18 @@ func (c *BTC) Sign(rawTx, privateKeyWif string) (signedRawTx string, err error)
return
}

// 32 + 33 (format+pubk)
func (c *BTC) RawKey() ([]byte, error) {
privk, err := c.derivePrivateKey()
if err != nil {
return nil, err
}
b := make([]byte, 0)
b = core.PaddedAppend(btcec.PrivKeyBytesLen, b, privk.D.Bytes())
b = append(b, privk.PubKey().SerializeCompressed()...)
return b, nil
}

// VerifySignature verifies rawTx's signature is intact
// If signedRawTx is not signed by pubKey, an error will raise.
func (c *BTC) VerifySignature(pubKey, rawTx, signedRawTx string) error {
Expand Down
62 changes: 38 additions & 24 deletions core/eth/internalized/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const (
symbol = "ETH"
)

var _ core.Coin = (*eth)(nil)

type eth struct {
core.CoinInfo
}
Expand Down Expand Up @@ -86,40 +88,24 @@ func (c *eth) DeriveAddress() (address string, err error) {
}

func (c *eth) DerivePublicKey() (publicKey string, err error) {
privateKeyECDSA, err := c.DerivePrivateKey()
ecPrivk, err := c.deriveECPrivateKey()
if err != nil {
return
return "", err
}

privateKey, err := crypto.HexToECDSA(privateKeyECDSA)
if err != nil {
return
}

public := privateKey.Public()
publicKeyECDSA, ok := public.(*ecdsa.PublicKey)
ecdsaPublicKey, ok := ecPrivk.Public().(*ecdsa.PublicKey)
if !ok {
err = errors.New("failed to get public key")
return
return "", errors.New("failed to get public key")
}
publicKey = hex.EncodeToString(crypto.FromECDSAPub(publicKeyECDSA))
publicKey = hex.EncodeToString(crypto.FromECDSAPub(ecdsaPublicKey))
return
}

func (c *eth) DerivePrivateKey() (privateKey string, err error) {
childKey := c.MasterKey
for _, childNum := range c.DerivationPath {
childKey, err = childKey.Child(childNum)
if err != nil {
return "", err
}
}

ECPrivateKey, err := childKey.ECPrivKey()
ecPrivk, err := c.deriveECPrivateKey()
if err != nil {
return
return "", err
}
privateKey = hex.EncodeToString(crypto.FromECDSA(ECPrivateKey.ToECDSA()))
privateKey = hex.EncodeToString(crypto.FromECDSA(ecPrivk))
return
}

Expand Down Expand Up @@ -219,6 +205,34 @@ func (c *eth) Sign(msg, privateKey string) (sig string, err error) {
return
}

func (c *eth) deriveECPrivateKey() (*ecdsa.PrivateKey, error) {
var err error
childKey := c.MasterKey
for _, childNum := range c.DerivationPath {
childKey, err = childKey.Child(childNum)
if err != nil {
return nil, err
}
}
ecPrivateKey, err := childKey.ECPrivKey()
if err != nil {
return nil, err
}
return ecPrivateKey.ToECDSA(), nil
}

func (c *eth) RawKey() ([]byte, error) {
ecPrivk, err := c.deriveECPrivateKey()
if err != nil {
return nil, err
}
ecdsaPublicKey, ok := ecPrivk.Public().(*ecdsa.PublicKey)
if !ok {
return nil, errors.New("failed to get public key")
}
return append(crypto.FromECDSA(ecPrivk), crypto.FromECDSAPub(ecdsaPublicKey)...), nil
}

// pubkey is eth address
func (c *eth) VerifySignature(address, msg, signature string) (err error) {
if !common.IsHexAddress(address) {
Expand Down
12 changes: 12 additions & 0 deletions core/trx/trx.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ func (c *trx) derivePrivateKey() (privateKey *ecdsa.PrivateKey, err error) {
return priKey.ToECDSA(), nil
}

func (c *trx) RawKey() ([]byte, error) {
ecPrivk, err := c.derivePrivateKey()
if err != nil {
return nil, err
}
ecdsaPublicKey, ok := ecPrivk.Public().(*ecdsa.PublicKey)
if !ok {
return nil, errors.New("failed to get public key")
}
return append(crypto.FromECDSA(ecPrivk), crypto.FromECDSAPub(ecdsaPublicKey)...), nil
}

func (c *trx) DerivePrivateKey() (privateKey string, err error) {
priKey, err := c.derivePrivateKey()
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions core/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type Coin interface {
Sign(msg, privateKey string) (sig string, err error)
// VerifySignature verifies rawTx's signature is intact
VerifySignature(pubKey, msg, signature string) error
// RawKey return raw private key, public key
RawKey() ([]byte, error)
}

type HasParentChain interface {
Expand Down
8 changes: 8 additions & 0 deletions core/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package core

func PaddedAppend(size uint, dst, src []byte) []byte {
for i := 0; i < int(size)-len(src); i++ {
dst = append(dst, 0)
}
return append(dst, src...)
}
9 changes: 9 additions & 0 deletions wallet/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ func (c Wallet) DerivePrivateKey(symbol string) (privateKey string, err error) {
return coin.DerivePrivateKey()
}

// RawKey 给出原始 私钥+公钥
func (c Wallet) RawKey(symbol string) ([]byte, error) {
coin, err := c.initCoin(symbol)
if err != nil {
return nil, err
}
return coin.RawKey()
}

// DecodeTx 解析交易数据
// return: json 数据
func (c Wallet) DecodeTx(symbol, msg string) (tx string, err error) {
Expand Down
22 changes: 22 additions & 0 deletions wallet/interface_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,28 @@ func TestBTCSegwit(t *testing.T) {

}

func ExampleDerive(t *testing.T) {
mnemonic := "connect auto goose panda extend ozone absent climb abstract doll west crazy"
var options WalletOptions
options.Add(WithPassword(""))
options.Add(WithPathFormat(bip44.FullPathFormat))
// options.Add(WithFlag(FlagBTCUseSegWitFormat))
w, err := BuildWalletFromMnemonic(
mnemonic,
false,
&options,
)
assert.NoError(t, err)

for _, s := range []string{"BTC", "BBC", "ETH", "TRX"} {
fmt.Println(s)
key, err := w.RawKey(s)
assert.NoError(t, err)
fmt.Println(len(key), key)
}

}

// 该测试验证不同的通用参数推导出不同的地址,以确保path/password确实生效
func TestCoin_DeriveAddressOptions(t *testing.T) {
const mnemonic = "lecture leg select like delay limit spread retire toward west grape bachelor"
Expand Down

0 comments on commit 8cf1f86

Please sign in to comment.