From 6ef08d6e7a5e69e9adf0359a7f3035ecacdc8469 Mon Sep 17 00:00:00 2001 From: ycen <44356973+yycen@users.noreply.github.com> Date: Thu, 26 Aug 2021 21:06:36 +0800 Subject: [PATCH 1/5] Cherrypick child key derivation (#140) * Cherrypick child_key_derivation from SwingbyProtocol https://github.com/SwingbyProtocol/tss-lib/pull/6/files#diff-e663957d1112b8c89bb7a782fe1cebe0d5e4d84a17861ae5af5cc0b59d1dbf56 * Add serialization to child key derivation add test case from github.com/btcsuite/hdkeychain * Making ec as parameter in key_derivation_util * Add version string to extendedkey, to comply with BIP32 --- crypto/ckd/child_key_derivation.go | 260 ++++++++++++++++++++++++ crypto/ckd/child_key_derivation_test.go | 130 ++++++++++++ crypto/ecpoint.go | 9 + ecdsa/resharing/local_party_test.go | 2 +- ecdsa/signing/key_derivation_util.go | 59 ++++++ ecdsa/signing/local_party.go | 3 + ecdsa/signing/local_party_test.go | 112 +++++++++- ecdsa/signing/round_1.go | 7 + 8 files changed, 580 insertions(+), 2 deletions(-) create mode 100644 crypto/ckd/child_key_derivation.go create mode 100644 crypto/ckd/child_key_derivation_test.go create mode 100644 ecdsa/signing/key_derivation_util.go diff --git a/crypto/ckd/child_key_derivation.go b/crypto/ckd/child_key_derivation.go new file mode 100644 index 00000000..da6e690b --- /dev/null +++ b/crypto/ckd/child_key_derivation.go @@ -0,0 +1,260 @@ +// Copyright © Swingby + +package ckd + +import ( + "bytes" + "crypto/ecdsa" + "crypto/hmac" + "crypto/rand" + "crypto/sha256" + "crypto/sha512" + "encoding/binary" + "errors" + "hash" + "math/big" + + "github.com/binance-chain/tss-lib/common" + "github.com/binance-chain/tss-lib/crypto" + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcutil/base58" + "golang.org/x/crypto/ripemd160" +) + +type ExtendedKey struct { + ecdsa.PublicKey + Depth uint8 + ChildIndex uint32 + ChainCode []byte // 32 bytes + ParentFP []byte // parent fingerprint + Version []byte +} + +// For more information about child key derivation see https://github.com/binance-chain/tss-lib/issues/104 +// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki . +// The functions below do not implement the full BIP-32 specification. As mentioned in the Jira ticket above, +// we only use non-hardened derived keys. + +const ( + + // HardenedKeyStart hardened key starts. + HardenedKeyStart = 0x80000000 // 2^31 + + // max Depth + maxDepth = 1<<8 - 1 + + PubKeyBytesLenCompressed = 33 + + pubKeyCompressed byte = 0x2 + + serializedKeyLen = 78 + + // MinSeedBytes is the minimum number of bytes allowed for a seed to + // a master node. + MinSeedBytes = 16 // 128 bits + + // MaxSeedBytes is the maximum number of bytes allowed for a seed to + // a master node. + MaxSeedBytes = 64 // 512 bits +) + +// Extended public key serialization, defined in BIP32 +func (k *ExtendedKey) String() string { + // version(4) || depth(1) || parentFP (4) || childinde(4) || chaincode (32) || key(33) || checksum(4) + var childNumBytes [4]byte + binary.BigEndian.PutUint32(childNumBytes[:], k.ChildIndex) + + serializedBytes := make([]byte, 0, serializedKeyLen + 4) + serializedBytes = append(serializedBytes, k.Version...) + serializedBytes = append(serializedBytes, k.Depth) + serializedBytes = append(serializedBytes, k.ParentFP...) + serializedBytes = append(serializedBytes, childNumBytes[:]...) + serializedBytes = append(serializedBytes, k.ChainCode...) + pubKeyBytes := serializeCompressed(k.PublicKey.X, k.PublicKey.Y) + serializedBytes = append(serializedBytes, pubKeyBytes...) + + checkSum := doubleHashB(serializedBytes)[:4] + serializedBytes = append(serializedBytes, checkSum...) + return base58.Encode(serializedBytes) +} + +// NewExtendedKeyFromString returns a new extended key from a base58-encoded extended key +func NewExtendedKeyFromString(key string) (*ExtendedKey, error) { + // version(4) || depth(1) || parentFP (4) || childinde(4) || chaincode (32) || key(33) || checksum(4) + + decoded := base58.Decode(key) + if len(decoded) != serializedKeyLen+4 { + return nil, errors.New("invalid extended key") + } + + // Split the payload and checksum up and ensure the checksum matches. + payload := decoded[:len(decoded)-4] + checkSum := decoded[len(decoded)-4:] + expectedCheckSum := doubleHashB(payload)[:4] + if !bytes.Equal(checkSum, expectedCheckSum) { + return nil, errors.New("invalid extended key") + } + + // Deserialize each of the payload fields. + version := payload[:4] + depth := payload[4:5][0] + parentFP := payload[5:9] + childNum := binary.BigEndian.Uint32(payload[9:13]) + chainCode := payload[13:45] + keyData := payload[45:78] + + // Ensure the public key parses correctly and is actually on the + // secp256k1 curve. + pubKey, err := btcec.ParsePubKey(keyData, btcec.S256()) + if err != nil { + return nil, err + } + + return &ExtendedKey{ + PublicKey: ecdsa.PublicKey(*pubKey), + Depth: depth, + ChildIndex: childNum, + ChainCode: chainCode, + ParentFP: parentFP, + Version: version, + }, nil +} + +func doubleHashB(b []byte) []byte { + first := sha256.Sum256(b) + second := sha256.Sum256(first[:]) + return second[:] +} + +func calcHash(buf []byte, hasher hash.Hash) []byte { + hasher.Write(buf) + return hasher.Sum(nil) +} + +func hash160(buf []byte) []byte { + return calcHash(calcHash(buf, sha256.New()), ripemd160.New()) +} + +func isOdd(a *big.Int) bool { + return a.Bit(0) == 1 +} + +// PaddedAppend append src to dst, if less than size padding 0 at start +func paddedAppend(dst []byte, srcPaddedSize int, src []byte) []byte { + return append(dst, paddedBytes(srcPaddedSize, src)...) +} + +// PaddedBytes padding byte array to size length +func paddedBytes(size int, src []byte) []byte { + offset := size - len(src) + tmp := src + if offset > 0 { + tmp = make([]byte, size) + copy(tmp[offset:], src) + } + return tmp +} + +// SerializeCompressed serializes a public key 33-byte compressed format +func serializeCompressed(publicKeyX *big.Int, publicKeyY *big.Int) []byte { + b := make([]byte, 0, PubKeyBytesLenCompressed) + format := pubKeyCompressed + if isOdd(publicKeyY) { + format |= 0x1 + } + b = append(b, format) + return paddedAppend(b, 32, publicKeyX.Bytes()) +} + +func DeriveChildKeyFromHierarchy(indicesHierarchy []uint32, pk *ExtendedKey, mod *big.Int) (*big.Int, *ExtendedKey, error) { + var k = pk + var err error + var childKey *ExtendedKey + mod_ := common.ModInt(mod) + ilNum := big.NewInt(0) + for index := range indicesHierarchy { + ilNumOld := ilNum + ilNum, childKey, err = DeriveChildKey(indicesHierarchy[index], k) + if err != nil { + return nil, nil, err + } + k = childKey + ilNum = mod_.Add(ilNum, ilNumOld) + } + return ilNum, k, nil +} + +// Derive a child key from the given parent key. The function returns "IL" ("I left"), per BIP-32 spec. It also +// returns the derived child key. +func DeriveChildKey(index uint32, pk *ExtendedKey) (*big.Int, *ExtendedKey, error) { + if index >= HardenedKeyStart { + return nil, nil, errors.New("the index must be non-hardened") + } + if pk.Depth == maxDepth { + return nil, nil, errors.New("cannot derive key beyond max depth") + } + + cryptoPk, err := crypto.NewECPoint(btcec.S256(), pk.X, pk.Y) + if err != nil { + common.Logger.Error("error getting pubkey from extendedkey") + return nil, nil, err + } + + pkPublicKeyBytes := serializeCompressed(pk.X, pk.Y) + + data := make([]byte, 37) + copy(data, pkPublicKeyBytes) + binary.BigEndian.PutUint32(data[33:], index) + + // I = HMAC-SHA512(Key = chainCode, Data=data) + hmac512 := hmac.New(sha512.New, pk.ChainCode) + hmac512.Write(data) + ilr := hmac512.Sum(nil) + il := ilr[:32] + childChainCode := ilr[32:] + ilNum := new(big.Int).SetBytes(il) + + if ilNum.Cmp(btcec.S256().N) >= 0 || ilNum.Sign() == 0 { + // falling outside of the valid range for curve private keys + err = errors.New("invalid derived key") + common.Logger.Error("error deriving child key") + return nil, nil, err + } + + deltaG := crypto.ScalarBaseMult(btcec.S256(), ilNum) + if deltaG.X().Sign() == 0 || deltaG.Y().Sign() == 0 { + err = errors.New("invalid child") + common.Logger.Error("error invalid child") + return nil, nil, err + } + childCryptoPk, err := cryptoPk.Add(deltaG) + if err != nil { + common.Logger.Error("error adding delta G to parent key") + return nil, nil, err + } + + childPk := &ExtendedKey{ + PublicKey: *childCryptoPk.ToECDSAPubKey(), + Depth: pk.Depth + 1, + ChildIndex: index, + ChainCode: childChainCode, + ParentFP: hash160(pkPublicKeyBytes)[:4], + Version: pk.Version, + } + return ilNum, childPk, nil +} + +func GenerateSeed(length uint8) ([]byte, error) { + // Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes]. + if length < MinSeedBytes || length > MaxSeedBytes { + return nil, errors.New("invalid seed length") + } + + buf := make([]byte, length) + _, err := rand.Read(buf) + if err != nil { + return nil, err + } + + return buf, nil +} \ No newline at end of file diff --git a/crypto/ckd/child_key_derivation_test.go b/crypto/ckd/child_key_derivation_test.go new file mode 100644 index 00000000..5b07c682 --- /dev/null +++ b/crypto/ckd/child_key_derivation_test.go @@ -0,0 +1,130 @@ +// Copyright © 2019 Binance +// +// This file is part of Binance. The full Binance copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +package ckd_test + +import ( + "testing" + + . "github.com/binance-chain/tss-lib/crypto/ckd" +) +func TestPublicDerivation(t *testing.T) { + // port from https://github.com/btcsuite/btcutil/blob/master/hdkeychain/extendedkey_test.go + // The public extended keys for test vectors in [BIP32]. + testVec1MasterPubKey := "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8" + testVec2MasterPubKey := "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB" + + tests := []struct { + name string + master string + path []uint32 + wantPub string + }{ + // Test vector 1 + { + name: "test vector 1 chain m", + master: testVec1MasterPubKey, + path: []uint32{}, + wantPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", + }, + { + name: "test vector 1 chain m/0", + master: testVec1MasterPubKey, + path: []uint32{0}, + wantPub: "xpub68Gmy5EVb2BdFbj2LpWrk1M7obNuaPTpT5oh9QCCo5sRfqSHVYWex97WpDZzszdzHzxXDAzPLVSwybe4uPYkSk4G3gnrPqqkV9RyNzAcNJ1", + }, + { + name: "test vector 1 chain m/0/1", + master: testVec1MasterPubKey, + path: []uint32{0, 1}, + wantPub: "xpub6AvUGrnEpfvJBbfx7sQ89Q8hEMPM65UteqEX4yUbUiES2jHfjexmfJoxCGSwFMZiPBaKQT1RiKWrKfuDV4vpgVs4Xn8PpPTR2i79rwHd4Zr", + }, + { + name: "test vector 1 chain m/0/1/2", + master: testVec1MasterPubKey, + path: []uint32{0, 1, 2}, + wantPub: "xpub6BqyndF6rhZqmgktFCBcapkwubGxPqoAZtQaYewJHXVKZcLdnqBVC8N6f6FSHWUghjuTLeubWyQWfJdk2G3tGgvgj3qngo4vLTnnSjAZckv", + }, + { + name: "test vector 1 chain m/0/1/2/2", + master: testVec1MasterPubKey, + path: []uint32{0, 1, 2, 2}, + wantPub: "xpub6FHUhLbYYkgFQiFrDiXRfQFXBB2msCxKTsNyAExi6keFxQ8sHfwpogY3p3s1ePSpUqLNYks5T6a3JqpCGszt4kxbyq7tUoFP5c8KWyiDtPp", + }, + { + name: "test vector 1 chain m/0/1/2/2/1000000000", + master: testVec1MasterPubKey, + path: []uint32{0, 1, 2, 2, 1000000000}, + wantPub: "xpub6GX3zWVgSgPc5tgjE6ogT9nfwSADD3tdsxpzd7jJoJMqSY12Be6VQEFwDCp6wAQoZsH2iq5nNocHEaVDxBcobPrkZCjYW3QUmoDYzMFBDu9", + }, + + // Test vector 2 + { + name: "test vector 2 chain m", + master: testVec2MasterPubKey, + path: []uint32{}, + wantPub: "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB", + }, + { + name: "test vector 2 chain m/0", + master: testVec2MasterPubKey, + path: []uint32{0}, + wantPub: "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH", + }, + { + name: "test vector 2 chain m/0/2147483647", + master: testVec2MasterPubKey, + path: []uint32{0, 2147483647}, + wantPub: "xpub6ASAVgeWMg4pmutghzHG3BohahjwNwPmy2DgM6W9wGegtPrvNgjBwuZRD7hSDFhYfunq8vDgwG4ah1gVzZysgp3UsKz7VNjCnSUJJ5T4fdD", + }, + { + name: "test vector 2 chain m/0/2147483647/1", + master: testVec2MasterPubKey, + path: []uint32{0, 2147483647, 1}, + wantPub: "xpub6CrnV7NzJy4VdgP5niTpqWJiFXMAca6qBm5Hfsry77SQmN1HGYHnjsZSujoHzdxf7ZNK5UVrmDXFPiEW2ecwHGWMFGUxPC9ARipss9rXd4b", + }, + { + name: "test vector 2 chain m/0/2147483647/1/2147483646", + master: testVec2MasterPubKey, + path: []uint32{0, 2147483647, 1, 2147483646}, + wantPub: "xpub6FL2423qFaWzHCvBndkN9cbkn5cysiUeFq4eb9t9kE88jcmY63tNuLNRzpHPdAM4dUpLhZ7aUm2cJ5zF7KYonf4jAPfRqTMTRBNkQL3Tfta", + }, + { + name: "test vector 2 chain m/0/2147483647/1/2147483646/2", + master: testVec2MasterPubKey, + path: []uint32{0, 2147483647, 1, 2147483646, 2}, + wantPub: "xpub6H7WkJf547AiSwAbX6xsm8Bmq9M9P1Gjequ5SipsjipWmtXSyp4C3uwzewedGEgAMsDy4jEvNTWtxLyqqHY9C12gaBmgUdk2CGmwachwnWK", + }, + } + +tests: + for i, test := range tests { + extKey, err := NewExtendedKeyFromString(test.master) + if err != nil { + t.Errorf("NewKeyFromString #%d (%s): unexpected error "+ + "creating extended key: %v", i, test.name, + err) + continue + } + + for _, childNum := range test.path { + var err error + _, extKey, err = DeriveChildKey(childNum, extKey) + if err != nil { + t.Errorf("err: %v", err) + continue tests + } + } + + pubStr := extKey.String() + if pubStr != test.wantPub { + t.Errorf("Derive #%d (%s): mismatched serialized "+ + "public extended key -- got: %s, want: %s", i, + test.name, pubStr, test.wantPub) + continue + } + } +} \ No newline at end of file diff --git a/crypto/ecpoint.go b/crypto/ecpoint.go index 26556eaf..879dbf48 100644 --- a/crypto/ecpoint.go +++ b/crypto/ecpoint.go @@ -8,6 +8,7 @@ package crypto import ( "bytes" + "crypto/ecdsa" "crypto/elliptic" "encoding/binary" "encoding/json" @@ -64,6 +65,14 @@ func (p *ECPoint) ScalarMult(k *big.Int) *ECPoint { return newP } +func (p *ECPoint) ToECDSAPubKey() *ecdsa.PublicKey { + return &ecdsa.PublicKey{ + Curve: p.curve, + X: p.X(), + Y: p.Y(), + } +} + func (p *ECPoint) IsOnCurve() bool { return isOnCurve(p.curve, p.coords[0], p.coords[1]) } diff --git a/ecdsa/resharing/local_party_test.go b/ecdsa/resharing/local_party_test.go index 8607e200..c46083c6 100644 --- a/ecdsa/resharing/local_party_test.go +++ b/ecdsa/resharing/local_party_test.go @@ -172,7 +172,7 @@ signing: for j, signPID := range signPIDs { params := tss.NewParameters(tss.S256(), signP2pCtx, signPID, len(signPIDs), newThreshold) - P := signing.NewLocalParty(big.NewInt(42), params, signKeys[j], signOutCh, signEndCh).(*signing.LocalParty) + P := signing.NewLocalParty(big.NewInt(42), params, signKeys[j], big.NewInt(0), signOutCh, signEndCh).(*signing.LocalParty) signParties = append(signParties, P) go func(P *signing.LocalParty) { if err := P.Start(); err != nil { diff --git a/ecdsa/signing/key_derivation_util.go b/ecdsa/signing/key_derivation_util.go new file mode 100644 index 00000000..f31a42d2 --- /dev/null +++ b/ecdsa/signing/key_derivation_util.go @@ -0,0 +1,59 @@ +// Copyright © 2021 Swingby + +package signing + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "math/big" + + "github.com/binance-chain/tss-lib/common" + "github.com/binance-chain/tss-lib/crypto" + "github.com/binance-chain/tss-lib/crypto/ckd" + "github.com/binance-chain/tss-lib/ecdsa/keygen" + + "github.com/btcsuite/btcd/chaincfg" +) + +func UpdatePublicKeyAndAdjustBigXj(keyDerivationDelta *big.Int, keys []keygen.LocalPartySaveData, extendedChildPk *ecdsa.PublicKey, ec elliptic.Curve) error { + var err error + gDelta := crypto.ScalarBaseMult(ec, keyDerivationDelta) + for k := range keys { + keys[k].ECDSAPub, err = crypto.NewECPoint(ec, extendedChildPk.X, extendedChildPk.Y) + if err != nil { + common.Logger.Errorf("error creating new extended child public key") + return err + } + // Suppose X_j has shamir shares X_j0, X_j1, ..., X_jn + // So X_j + D has shamir shares X_j0 + D, X_j1 + D, ..., X_jn + D + for j := range keys[k].BigXj { + keys[k].BigXj[j], err = keys[k].BigXj[j].Add(gDelta) + if err != nil { + common.Logger.Errorf("error in delta operation") + return err + } + } + } + return nil +} + +func derivingPubkeyFromPath(masterPub *crypto.ECPoint, chainCode []byte, path []uint32, ec elliptic.Curve) (*big.Int, *ckd.ExtendedKey, error) { + // build ecdsa key pair + pk := ecdsa.PublicKey{ + Curve: ec, + X: masterPub.X(), + Y: masterPub.Y(), + } + + net := &chaincfg.MainNetParams + extendedParentPk := &ckd.ExtendedKey{ + PublicKey: pk, + Depth: 0, + ChildIndex: 0, + ChainCode: chainCode[:], + ParentFP: []byte{0x00, 0x00, 0x00, 0x00}, + Version: net.HDPrivateKeyID[:], + } + + return ckd.DeriveChildKeyFromHierarchy(path, extendedParentPk, ec.Params().N) +} diff --git a/ecdsa/signing/local_party.go b/ecdsa/signing/local_party.go index 8c3182ae..ae32c314 100644 --- a/ecdsa/signing/local_party.go +++ b/ecdsa/signing/local_party.go @@ -61,6 +61,7 @@ type ( theta, thetaInverse, sigma, + keyDerivationDelta, gamma *big.Int cis []*big.Int bigWs []*crypto.ECPoint @@ -97,6 +98,7 @@ func NewLocalParty( msg *big.Int, params *tss.Parameters, key keygen.LocalPartySaveData, + keyDerivationDelta *big.Int, out chan<- tss.Message, end chan<- common.SignatureData, ) tss.Party { @@ -122,6 +124,7 @@ func NewLocalParty( p.temp.signRound8Messages = make([]tss.ParsedMessage, partyCount) p.temp.signRound9Messages = make([]tss.ParsedMessage, partyCount) // temp data init + p.temp.keyDerivationDelta = keyDerivationDelta p.temp.m = msg p.temp.cis = make([]*big.Int, partyCount) p.temp.bigWs = make([]*crypto.ECPoint, partyCount) diff --git a/ecdsa/signing/local_party_test.go b/ecdsa/signing/local_party_test.go index 74b80eb6..ce01ef4a 100644 --- a/ecdsa/signing/local_party_test.go +++ b/ecdsa/signing/local_party_test.go @@ -14,6 +14,7 @@ import ( "sync/atomic" "testing" + "github.com/btcsuite/btcd/btcec" "github.com/ipfs/go-log" "github.com/stretchr/testify/assert" @@ -59,7 +60,8 @@ func TestE2EConcurrent(t *testing.T) { for i := 0; i < len(signPIDs); i++ { params := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold) - P := NewLocalParty(big.NewInt(42), params, keys[i], outCh, endCh).(*LocalParty) + keyDerivationDelta := big.NewInt(0) + P := NewLocalParty(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh).(*LocalParty) parties = append(parties, P) go func(P *LocalParty) { if err := P.Start(); err != nil { @@ -130,6 +132,114 @@ signing: } } +func TestE2EWithHDKeyDerivation(t *testing.T) { + setUp("info") + threshold := testThreshold + + // PHASE: load keygen fixtures + keys, signPIDs, err := keygen.LoadKeygenTestFixturesRandomSet(testThreshold+1, testParticipants) + assert.NoError(t, err, "should load keygen fixtures") + assert.Equal(t, testThreshold+1, len(keys)) + assert.Equal(t, testThreshold+1, len(signPIDs)) + + chainCode := make([]byte, 32) + max32b := new(big.Int).Lsh(new(big.Int).SetUint64(1), 256) + max32b = new(big.Int).Sub(max32b, new(big.Int).SetUint64(1)) + common.GetRandomPositiveInt(max32b).FillBytes(chainCode) + + il, extendedChildPk, errorDerivation := derivingPubkeyFromPath(keys[0].ECDSAPub, chainCode, []uint32{12, 209, 3}, btcec.S256()) + assert.NoErrorf(t, errorDerivation, "there should not be an error deriving the child public key") + + keyDerivationDelta := il + + err = UpdatePublicKeyAndAdjustBigXj(keyDerivationDelta, keys, &extendedChildPk.PublicKey, btcec.S256()) + assert.NoErrorf(t, err, "there should not be an error setting the derived keys") + + // PHASE: signing + // use a shuffled selection of the list of parties for this test + p2pCtx := tss.NewPeerContext(signPIDs) + parties := make([]*LocalParty, 0, len(signPIDs)) + + errCh := make(chan *tss.Error, len(signPIDs)) + outCh := make(chan tss.Message, len(signPIDs)) + endCh := make(chan common.SignatureData, len(signPIDs)) + + updater := test.SharedPartyUpdater + + // init the parties + for i := 0; i < len(signPIDs); i++ { + params := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold) + + P := NewLocalParty(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh).(*LocalParty) + parties = append(parties, P) + go func(P *LocalParty) { + if err := P.Start(); err != nil { + errCh <- err + } + }(P) + } + + var ended int32 +signing: + for { + select { + case err := <-errCh: + common.Logger.Errorf("Error: %s", err) + assert.FailNow(t, err.Error()) + break signing + + case msg := <-outCh: + dest := msg.GetTo() + if dest == nil { + for _, P := range parties { + if P.PartyID().Index == msg.GetFrom().Index { + continue + } + go updater(P, msg, errCh) + } + } else { + if dest[0].Index == msg.GetFrom().Index { + t.Fatalf("party %d tried to send a message to itself (%d)", dest[0].Index, msg.GetFrom().Index) + } + go updater(parties[dest[0].Index], msg, errCh) + } + + case <-endCh: + atomic.AddInt32(&ended, 1) + if atomic.LoadInt32(&ended) == int32(len(signPIDs)) { + t.Logf("Done. Received signature data from %d participants", ended) + R := parties[0].temp.bigR + r := parties[0].temp.rx + fmt.Printf("sign result: R(%s, %s), r=%s\n", R.X().String(), R.Y().String(), r.String()) + + modN := common.ModInt(tss.S256().Params().N) + + // BEGIN check s correctness + sumS := big.NewInt(0) + for _, p := range parties { + sumS = modN.Add(sumS, p.temp.si) + } + fmt.Printf("S: %s\n", sumS.String()) + // END check s correctness + + // BEGIN ECDSA verify + pkX, pkY := keys[0].ECDSAPub.X(), keys[0].ECDSAPub.Y() + pk := ecdsa.PublicKey{ + Curve: tss.EC(), + X: pkX, + Y: pkY, + } + ok := ecdsa.Verify(&pk, big.NewInt(42).Bytes(), R.X(), sumS) + assert.True(t, ok, "ecdsa verify must pass") + t.Log("ECDSA signing test done.") + // END ECDSA verify + + break signing + } + } + } +} + func TestFillTo32BytesInPlace(t *testing.T) { s := big.NewInt(123456789) normalizedS := padToLengthBytesInPlace(s.Bytes(), 32) diff --git a/ecdsa/signing/round_1.go b/ecdsa/signing/round_1.go index 4672732e..908e1300 100644 --- a/ecdsa/signing/round_1.go +++ b/ecdsa/signing/round_1.go @@ -121,6 +121,13 @@ func (round *round1) prepare() error { ks := round.key.Ks bigXs := round.key.BigXj + // adding the key derivation delta to the xi's + // Suppose x has shamir shares x_0, x_1, ..., x_n + // So x + D has shamir shares x_0 + D, x_1 + D, ..., x_n + D + mod := common.ModInt(round.Params().EC().Params().N) + xi = mod.Add(round.temp.keyDerivationDelta, xi) + round.key.Xi = xi + if round.Threshold()+1 > len(ks) { return fmt.Errorf("t+1=%d is not satisfied by the key count of %d", round.Threshold()+1, len(ks)) } From d3386814fbd5059204d0961252b046f0bed5c190 Mon Sep 17 00:00:00 2001 From: FitzLu Date: Wed, 8 Sep 2021 13:00:50 +0800 Subject: [PATCH 2/5] specify curve in NewExtendedKey --- crypto/ckd/child_key_derivation.go | 43 ++++++++++++++++--------- crypto/ckd/child_key_derivation_test.go | 6 ++-- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/crypto/ckd/child_key_derivation.go b/crypto/ckd/child_key_derivation.go index da6e690b..14ebedf5 100644 --- a/crypto/ckd/child_key_derivation.go +++ b/crypto/ckd/child_key_derivation.go @@ -5,6 +5,7 @@ package ckd import ( "bytes" "crypto/ecdsa" + "crypto/elliptic" "crypto/hmac" "crypto/rand" "crypto/sha256" @@ -63,8 +64,8 @@ func (k *ExtendedKey) String() string { // version(4) || depth(1) || parentFP (4) || childinde(4) || chaincode (32) || key(33) || checksum(4) var childNumBytes [4]byte binary.BigEndian.PutUint32(childNumBytes[:], k.ChildIndex) - - serializedBytes := make([]byte, 0, serializedKeyLen + 4) + + serializedBytes := make([]byte, 0, serializedKeyLen+4) serializedBytes = append(serializedBytes, k.Version...) serializedBytes = append(serializedBytes, k.Depth) serializedBytes = append(serializedBytes, k.ParentFP...) @@ -79,7 +80,7 @@ func (k *ExtendedKey) String() string { } // NewExtendedKeyFromString returns a new extended key from a base58-encoded extended key -func NewExtendedKeyFromString(key string) (*ExtendedKey, error) { +func NewExtendedKeyFromString(key string, curve elliptic.Curve) (*ExtendedKey, error) { // version(4) || depth(1) || parentFP (4) || childinde(4) || chaincode (32) || key(33) || checksum(4) decoded := base58.Decode(key) @@ -103,20 +104,32 @@ func NewExtendedKeyFromString(key string) (*ExtendedKey, error) { chainCode := payload[13:45] keyData := payload[45:78] - // Ensure the public key parses correctly and is actually on the - // secp256k1 curve. - pubKey, err := btcec.ParsePubKey(keyData, btcec.S256()) - if err != nil { - return nil, err + var pubKey ecdsa.PublicKey + + if c, ok := curve.(*btcec.KoblitzCurve); ok { + // Ensure the public key parses correctly and is actually on the + // secp256k1 curve. + pk, err := btcec.ParsePubKey(keyData, c) + if err != nil { + return nil, err + } + pubKey = ecdsa.PublicKey(*pk) + } else { + px, py := elliptic.Unmarshal(curve, keyData) + pubKey = ecdsa.PublicKey{ + Curve: curve, + X: px, + Y: py, + } } return &ExtendedKey{ - PublicKey: ecdsa.PublicKey(*pubKey), - Depth: depth, + PublicKey: pubKey, + Depth: depth, ChildIndex: childNum, - ChainCode: chainCode, - ParentFP: parentFP, - Version: version, + ChainCode: chainCode, + ParentFP: parentFP, + Version: version, }, nil } @@ -214,7 +227,7 @@ func DeriveChildKey(index uint32, pk *ExtendedKey) (*big.Int, *ExtendedKey, erro childChainCode := ilr[32:] ilNum := new(big.Int).SetBytes(il) - if ilNum.Cmp(btcec.S256().N) >= 0 || ilNum.Sign() == 0 { + if ilNum.Cmp(btcec.S256().N) >= 0 || ilNum.Sign() == 0 { // falling outside of the valid range for curve private keys err = errors.New("invalid derived key") common.Logger.Error("error deriving child key") @@ -257,4 +270,4 @@ func GenerateSeed(length uint8) ([]byte, error) { } return buf, nil -} \ No newline at end of file +} diff --git a/crypto/ckd/child_key_derivation_test.go b/crypto/ckd/child_key_derivation_test.go index 5b07c682..9ba75a5f 100644 --- a/crypto/ckd/child_key_derivation_test.go +++ b/crypto/ckd/child_key_derivation_test.go @@ -10,7 +10,9 @@ import ( "testing" . "github.com/binance-chain/tss-lib/crypto/ckd" + "github.com/btcsuite/btcd/btcec" ) + func TestPublicDerivation(t *testing.T) { // port from https://github.com/btcsuite/btcutil/blob/master/hdkeychain/extendedkey_test.go // The public extended keys for test vectors in [BIP32]. @@ -102,7 +104,7 @@ func TestPublicDerivation(t *testing.T) { tests: for i, test := range tests { - extKey, err := NewExtendedKeyFromString(test.master) + extKey, err := NewExtendedKeyFromString(test.master, btcec.S256()) if err != nil { t.Errorf("NewKeyFromString #%d (%s): unexpected error "+ "creating extended key: %v", i, test.name, @@ -127,4 +129,4 @@ tests: continue } } -} \ No newline at end of file +} From ac909ab10b6029c016818b6a8fc9f1bd0682786c Mon Sep 17 00:00:00 2001 From: FitzLu Date: Wed, 8 Sep 2021 13:35:37 +0800 Subject: [PATCH 3/5] pass curve in DeriveChildKey --- crypto/ckd/child_key_derivation.go | 14 +++++++------- crypto/ckd/child_key_derivation_test.go | 2 +- ecdsa/signing/key_derivation_util.go | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crypto/ckd/child_key_derivation.go b/crypto/ckd/child_key_derivation.go index 14ebedf5..c906d302 100644 --- a/crypto/ckd/child_key_derivation.go +++ b/crypto/ckd/child_key_derivation.go @@ -179,7 +179,7 @@ func serializeCompressed(publicKeyX *big.Int, publicKeyY *big.Int) []byte { return paddedAppend(b, 32, publicKeyX.Bytes()) } -func DeriveChildKeyFromHierarchy(indicesHierarchy []uint32, pk *ExtendedKey, mod *big.Int) (*big.Int, *ExtendedKey, error) { +func DeriveChildKeyFromHierarchy(indicesHierarchy []uint32, pk *ExtendedKey, mod *big.Int, curve elliptic.Curve) (*big.Int, *ExtendedKey, error) { var k = pk var err error var childKey *ExtendedKey @@ -187,7 +187,7 @@ func DeriveChildKeyFromHierarchy(indicesHierarchy []uint32, pk *ExtendedKey, mod ilNum := big.NewInt(0) for index := range indicesHierarchy { ilNumOld := ilNum - ilNum, childKey, err = DeriveChildKey(indicesHierarchy[index], k) + ilNum, childKey, err = DeriveChildKey(indicesHierarchy[index], k, curve) if err != nil { return nil, nil, err } @@ -197,9 +197,9 @@ func DeriveChildKeyFromHierarchy(indicesHierarchy []uint32, pk *ExtendedKey, mod return ilNum, k, nil } -// Derive a child key from the given parent key. The function returns "IL" ("I left"), per BIP-32 spec. It also +// DeriveChildKey Derive a child key from the given parent key. The function returns "IL" ("I left"), per BIP-32 spec. It also // returns the derived child key. -func DeriveChildKey(index uint32, pk *ExtendedKey) (*big.Int, *ExtendedKey, error) { +func DeriveChildKey(index uint32, pk *ExtendedKey, curve elliptic.Curve) (*big.Int, *ExtendedKey, error) { if index >= HardenedKeyStart { return nil, nil, errors.New("the index must be non-hardened") } @@ -207,7 +207,7 @@ func DeriveChildKey(index uint32, pk *ExtendedKey) (*big.Int, *ExtendedKey, erro return nil, nil, errors.New("cannot derive key beyond max depth") } - cryptoPk, err := crypto.NewECPoint(btcec.S256(), pk.X, pk.Y) + cryptoPk, err := crypto.NewECPoint(curve, pk.X, pk.Y) if err != nil { common.Logger.Error("error getting pubkey from extendedkey") return nil, nil, err @@ -227,14 +227,14 @@ func DeriveChildKey(index uint32, pk *ExtendedKey) (*big.Int, *ExtendedKey, erro childChainCode := ilr[32:] ilNum := new(big.Int).SetBytes(il) - if ilNum.Cmp(btcec.S256().N) >= 0 || ilNum.Sign() == 0 { + if ilNum.Cmp(curve.Params().N) >= 0 || ilNum.Sign() == 0 { // falling outside of the valid range for curve private keys err = errors.New("invalid derived key") common.Logger.Error("error deriving child key") return nil, nil, err } - deltaG := crypto.ScalarBaseMult(btcec.S256(), ilNum) + deltaG := crypto.ScalarBaseMult(curve, ilNum) if deltaG.X().Sign() == 0 || deltaG.Y().Sign() == 0 { err = errors.New("invalid child") common.Logger.Error("error invalid child") diff --git a/crypto/ckd/child_key_derivation_test.go b/crypto/ckd/child_key_derivation_test.go index 9ba75a5f..b1aa12b3 100644 --- a/crypto/ckd/child_key_derivation_test.go +++ b/crypto/ckd/child_key_derivation_test.go @@ -114,7 +114,7 @@ tests: for _, childNum := range test.path { var err error - _, extKey, err = DeriveChildKey(childNum, extKey) + _, extKey, err = DeriveChildKey(childNum, extKey, btcec.S256()) if err != nil { t.Errorf("err: %v", err) continue tests diff --git a/ecdsa/signing/key_derivation_util.go b/ecdsa/signing/key_derivation_util.go index f31a42d2..243c33b3 100644 --- a/ecdsa/signing/key_derivation_util.go +++ b/ecdsa/signing/key_derivation_util.go @@ -55,5 +55,5 @@ func derivingPubkeyFromPath(masterPub *crypto.ECPoint, chainCode []byte, path [] Version: net.HDPrivateKeyID[:], } - return ckd.DeriveChildKeyFromHierarchy(path, extendedParentPk, ec.Params().N) + return ckd.DeriveChildKeyFromHierarchy(path, extendedParentPk, ec.Params().N, ec) } From 9684c8f3d5d23f3ab88c63fee0c381ebd78221c2 Mon Sep 17 00:00:00 2001 From: pablo Date: Sat, 20 Aug 2022 17:07:54 +0300 Subject: [PATCH 4/5] amend the HD cherry pick not to break the existing API of NewLocalParty --- crypto/ckd/child_key_derivation.go | 20 ++------------------ crypto/ckd/child_key_derivation_test.go | 2 +- ecdsa/resharing/local_party_test.go | 2 +- ecdsa/signing/key_derivation_util.go | 8 ++++---- ecdsa/signing/local_party.go | 10 ++++++++++ ecdsa/signing/local_party_test.go | 7 +++---- ecdsa/signing/round_1.go | 14 ++++++++------ go.mod | 2 ++ go.sum | 2 ++ 9 files changed, 33 insertions(+), 34 deletions(-) diff --git a/crypto/ckd/child_key_derivation.go b/crypto/ckd/child_key_derivation.go index c906d302..6d188d3a 100644 --- a/crypto/ckd/child_key_derivation.go +++ b/crypto/ckd/child_key_derivation.go @@ -7,7 +7,6 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/hmac" - "crypto/rand" "crypto/sha256" "crypto/sha512" "encoding/binary" @@ -15,8 +14,8 @@ import ( "hash" "math/big" - "github.com/binance-chain/tss-lib/common" - "github.com/binance-chain/tss-lib/crypto" + "github.com/bnb-chain/tss-lib/common" + "github.com/bnb-chain/tss-lib/crypto" "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcutil/base58" "golang.org/x/crypto/ripemd160" @@ -256,18 +255,3 @@ func DeriveChildKey(index uint32, pk *ExtendedKey, curve elliptic.Curve) (*big.I } return ilNum, childPk, nil } - -func GenerateSeed(length uint8) ([]byte, error) { - // Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes]. - if length < MinSeedBytes || length > MaxSeedBytes { - return nil, errors.New("invalid seed length") - } - - buf := make([]byte, length) - _, err := rand.Read(buf) - if err != nil { - return nil, err - } - - return buf, nil -} diff --git a/crypto/ckd/child_key_derivation_test.go b/crypto/ckd/child_key_derivation_test.go index b1aa12b3..a065b9d9 100644 --- a/crypto/ckd/child_key_derivation_test.go +++ b/crypto/ckd/child_key_derivation_test.go @@ -9,7 +9,7 @@ package ckd_test import ( "testing" - . "github.com/binance-chain/tss-lib/crypto/ckd" + . "github.com/bnb-chain/tss-lib/crypto/ckd" "github.com/btcsuite/btcd/btcec" ) diff --git a/ecdsa/resharing/local_party_test.go b/ecdsa/resharing/local_party_test.go index c46083c6..8607e200 100644 --- a/ecdsa/resharing/local_party_test.go +++ b/ecdsa/resharing/local_party_test.go @@ -172,7 +172,7 @@ signing: for j, signPID := range signPIDs { params := tss.NewParameters(tss.S256(), signP2pCtx, signPID, len(signPIDs), newThreshold) - P := signing.NewLocalParty(big.NewInt(42), params, signKeys[j], big.NewInt(0), signOutCh, signEndCh).(*signing.LocalParty) + P := signing.NewLocalParty(big.NewInt(42), params, signKeys[j], signOutCh, signEndCh).(*signing.LocalParty) signParties = append(signParties, P) go func(P *signing.LocalParty) { if err := P.Start(); err != nil { diff --git a/ecdsa/signing/key_derivation_util.go b/ecdsa/signing/key_derivation_util.go index 243c33b3..e5826a71 100644 --- a/ecdsa/signing/key_derivation_util.go +++ b/ecdsa/signing/key_derivation_util.go @@ -7,10 +7,10 @@ import ( "crypto/elliptic" "math/big" - "github.com/binance-chain/tss-lib/common" - "github.com/binance-chain/tss-lib/crypto" - "github.com/binance-chain/tss-lib/crypto/ckd" - "github.com/binance-chain/tss-lib/ecdsa/keygen" + "github.com/bnb-chain/tss-lib/common" + "github.com/bnb-chain/tss-lib/crypto" + "github.com/bnb-chain/tss-lib/crypto/ckd" + "github.com/bnb-chain/tss-lib/ecdsa/keygen" "github.com/btcsuite/btcd/chaincfg" ) diff --git a/ecdsa/signing/local_party.go b/ecdsa/signing/local_party.go index ae32c314..ae202590 100644 --- a/ecdsa/signing/local_party.go +++ b/ecdsa/signing/local_party.go @@ -95,6 +95,16 @@ type ( ) func NewLocalParty( + msg *big.Int, + params *tss.Parameters, + key keygen.LocalPartySaveData, + out chan<- tss.Message, + end chan<- common.SignatureData) tss.Party { + return NewLocalPartyWithKDD(msg, params, key, nil, out, end) +} + +// NewLocalPartyWithKDD returns a party with key derivation delta for HD support +func NewLocalPartyWithKDD( msg *big.Int, params *tss.Parameters, key keygen.LocalPartySaveData, diff --git a/ecdsa/signing/local_party_test.go b/ecdsa/signing/local_party_test.go index ce01ef4a..acf772ce 100644 --- a/ecdsa/signing/local_party_test.go +++ b/ecdsa/signing/local_party_test.go @@ -60,8 +60,7 @@ func TestE2EConcurrent(t *testing.T) { for i := 0; i < len(signPIDs); i++ { params := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold) - keyDerivationDelta := big.NewInt(0) - P := NewLocalParty(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh).(*LocalParty) + P := NewLocalParty(big.NewInt(42), params, keys[i], outCh, endCh).(*LocalParty) parties = append(parties, P) go func(P *LocalParty) { if err := P.Start(); err != nil { @@ -169,8 +168,8 @@ func TestE2EWithHDKeyDerivation(t *testing.T) { // init the parties for i := 0; i < len(signPIDs); i++ { params := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold) - - P := NewLocalParty(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh).(*LocalParty) + + P := NewLocalPartyWithKDD(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh).(*LocalParty) parties = append(parties, P) go func(P *LocalParty) { if err := P.Start(); err != nil { diff --git a/ecdsa/signing/round_1.go b/ecdsa/signing/round_1.go index 908e1300..920930db 100644 --- a/ecdsa/signing/round_1.go +++ b/ecdsa/signing/round_1.go @@ -121,12 +121,14 @@ func (round *round1) prepare() error { ks := round.key.Ks bigXs := round.key.BigXj - // adding the key derivation delta to the xi's - // Suppose x has shamir shares x_0, x_1, ..., x_n - // So x + D has shamir shares x_0 + D, x_1 + D, ..., x_n + D - mod := common.ModInt(round.Params().EC().Params().N) - xi = mod.Add(round.temp.keyDerivationDelta, xi) - round.key.Xi = xi + if round.temp.keyDerivationDelta != nil { + // adding the key derivation delta to the xi's + // Suppose x has shamir shares x_0, x_1, ..., x_n + // So x + D has shamir shares x_0 + D, x_1 + D, ..., x_n + D + mod := common.ModInt(round.Params().EC().Params().N) + xi = mod.Add(round.temp.keyDerivationDelta, xi) + round.key.Xi = xi + } if round.Threshold()+1 > len(ks) { return fmt.Errorf("t+1=%d is not satisfied by the key count of %d", round.Threshold()+1, len(ks)) diff --git a/go.mod b/go.mod index 843c9cef..c5d5426f 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.16 require ( github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8 + github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/edwards/v2 v2.0.0 github.com/hashicorp/go-multierror v1.0.0 @@ -15,6 +16,7 @@ require ( github.com/otiai10/primes v0.0.0-20180210170552-f6d2a1ba97c4 github.com/pkg/errors v0.8.1 github.com/stretchr/testify v1.3.0 + golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44 golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7 // indirect google.golang.org/protobuf v1.27.1 ) diff --git a/go.sum b/go.sum index eee8502d..ab3fee3c 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,7 @@ github.com/binance-chain/edwards25519 v0.0.0-20200305024217-f36fc4b53d43/go.mod github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8 h1:mOg8/RgDSHTQ1R0IR+LMDuW4TDShPv+JzYHuR4GLoNA= github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= @@ -63,6 +64,7 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44 h1:9lP3x0pW80sDI6t1UMSLA4to18W7R7imwAI/sWS9S8Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From 4380f4d0df8a9b15bfba99850dfe7b376c76707b Mon Sep 17 00:00:00 2001 From: pablo Date: Thu, 1 Sep 2022 10:29:08 +0300 Subject: [PATCH 5/5] FillBytes not available in go 1.13 Fix test using FillBytes --- ecdsa/signing/local_party_test.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/ecdsa/signing/local_party_test.go b/ecdsa/signing/local_party_test.go index acf772ce..51b83873 100644 --- a/ecdsa/signing/local_party_test.go +++ b/ecdsa/signing/local_party_test.go @@ -144,7 +144,7 @@ func TestE2EWithHDKeyDerivation(t *testing.T) { chainCode := make([]byte, 32) max32b := new(big.Int).Lsh(new(big.Int).SetUint64(1), 256) max32b = new(big.Int).Sub(max32b, new(big.Int).SetUint64(1)) - common.GetRandomPositiveInt(max32b).FillBytes(chainCode) + fillBytes(common.GetRandomPositiveInt(max32b), chainCode) il, extendedChildPk, errorDerivation := derivingPubkeyFromPath(keys[0].ECDSAPub, chainCode, []uint32{12, 209, 3}, btcec.S256()) assert.NoErrorf(t, errorDerivation, "there should not be an error deriving the child public key") @@ -246,3 +246,19 @@ func TestFillTo32BytesInPlace(t *testing.T) { assert.Equal(t, 32, len(normalizedS)) assert.NotEqual(t, 32, len(s.Bytes())) } + +func fillBytes(x *big.Int, buf []byte) []byte { + b := x.Bytes() + if len(b) > len(buf) { + panic("buffer too small") + } + offset := len(buf) - len(b) + for i := range buf { + if i < offset { + buf[i] = 0 + } else { + buf[i] = b[i-offset] + } + } + return buf +}