Skip to content
Open
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 e2e/cmd/generate-preparams/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
"path/filepath"
"time"

"github.com/bnb-chain/tss-lib/v2/ecdsa/keygen"
"github.com/bnb-chain/tss-lib/v3/ecdsa/keygen"
)

const numNodes = 3
Expand Down
5 changes: 3 additions & 2 deletions e2e/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/fystack/mpcium/e2e
go 1.25.8

require (
github.com/bnb-chain/tss-lib/v2 v2.0.2
github.com/bnb-chain/tss-lib/v3 v3.0.1
github.com/dgraph-io/badger/v4 v4.9.0
github.com/fystack/mpcium v0.0.0-00010101000000-000000000000
github.com/google/uuid v1.6.0
Expand All @@ -15,6 +15,7 @@ require (

require (
filippo.io/age v1.3.1 // indirect
filippo.io/bigmod v0.1.0 // indirect
filippo.io/hpke v0.4.0 // indirect
github.com/agl/ed25519 v0.0.0-20200225211852-fd4d107ace12 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
Expand Down Expand Up @@ -104,4 +105,4 @@ replace github.com/fystack/mpcium => ../

replace github.com/agl/ed25519 => github.com/binance-chain/edwards25519 v0.0.0-20200305024217-f36fc4b53d43

replace github.com/bnb-chain/tss-lib/v2 => github.com/fystack/tss-lib/v2 v2.0.3
replace github.com/bnb-chain/tss-lib/v3 => github.com/fystack/tss-lib/v3 v3.0.1
85 changes: 4 additions & 81 deletions e2e/go.sum

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions examples/hdwallet/eddsa/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
"syscall"
"time"

tsscrypto "github.com/bnb-chain/tss-lib/v2/crypto"
"github.com/bnb-chain/tss-lib/v2/tss"
tsscrypto "github.com/bnb-chain/tss-lib/v3/crypto"
"github.com/bnb-chain/tss-lib/v3/tss"
"github.com/btcsuite/btcutil/base58"
"github.com/decred/dcrd/dcrec/edwards/v2"
"github.com/fystack/mpcium/pkg/ckdutil"
Expand Down Expand Up @@ -413,8 +413,8 @@ func deriveChildPublicKeyEd25519ViaTSS(masterPubKey []byte, chainCodeHex string,

childPub := edwards.PublicKey{
Curve: tss.Edwards(),
X: childKey.PublicKey.X(),
Y: childKey.PublicKey.Y(),
X: childKey.PublicKey.X,
Y: childKey.PublicKey.Y,
}

return childPub.SerializeCompressed(), nil
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/aws/aws-sdk-go-v2/config v1.32.7
github.com/aws/aws-sdk-go-v2/credentials v1.19.7
github.com/aws/aws-sdk-go-v2/service/kms v1.49.5
github.com/bnb-chain/tss-lib/v2 v2.0.2
github.com/bnb-chain/tss-lib/v3 v3.0.1
github.com/btcsuite/btcd v0.25.0
github.com/btcsuite/btcd/btcec/v2 v2.3.6
github.com/btcsuite/btcutil v1.0.2
Expand All @@ -28,6 +28,7 @@ require (
)

require (
filippo.io/bigmod v0.1.0 // indirect
filippo.io/hpke v0.4.0 // indirect
github.com/agl/ed25519 v0.0.0-20200225211852-fd4d107ace12 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
Expand Down Expand Up @@ -103,4 +104,4 @@ require (

replace github.com/agl/ed25519 => github.com/binance-chain/edwards25519 v0.0.0-20200305024217-f36fc4b53d43

replace github.com/bnb-chain/tss-lib/v2 => github.com/fystack/tss-lib/v2 v2.0.3
replace github.com/bnb-chain/tss-lib/v3 => github.com/fystack/tss-lib/v3 v3.0.1
85 changes: 4 additions & 81 deletions go.sum

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions pkg/ckdutil/child_derivation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"encoding/hex"
"testing"

tsscrypto "github.com/bnb-chain/tss-lib/v2/crypto"
"github.com/bnb-chain/tss-lib/v2/tss"
tsscrypto "github.com/bnb-chain/tss-lib/v3/crypto"
"github.com/bnb-chain/tss-lib/v3/tss"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/decred/dcrd/dcrec/edwards/v2"
"github.com/fystack/mpcium/pkg/mpc"
Expand Down Expand Up @@ -42,7 +42,7 @@ func TestEd25519StandaloneMatchesTSS(t *testing.T) {
_, tssChild, err := ckd.Derive("wallet-ed25519-test", masterPoint, path, tss.Edwards())
require.NoErrorf(t, err, "tss derivation failed at index %d", i)

tssPub := edwards.PublicKey{Curve: curve, X: tssChild.PublicKey.X(), Y: tssChild.PublicKey.Y()}
tssPub := edwards.PublicKey{Curve: curve, X: tssChild.PublicKey.X, Y: tssChild.PublicKey.Y}
require.Equalf(t, tssPub.SerializeCompressed(), localChild, "pubkey mismatch at index %d", i)
}
}
Expand Down Expand Up @@ -73,7 +73,7 @@ func TestSecp256k1StandaloneMatchesTSS(t *testing.T) {
_, tssChild, err := ckd.Derive("wallet-secp-test", masterPoint, path, tss.S256())
require.NoErrorf(t, err, "tss derivation failed at index %d", i)

tssChildBytes := serializeCompressed(tssChild.PublicKey.X(), tssChild.PublicKey.Y())
tssChildBytes := serializeCompressed(tssChild.PublicKey.X, tssChild.PublicKey.Y)
require.Equalf(t, tssChildBytes, localChild, "pubkey mismatch at index %d", i)
}
}
71 changes: 71 additions & 0 deletions pkg/ckdutil/golden_compat_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package ckdutil

import (
"encoding/hex"
"testing"

tsscrypto "github.com/bnb-chain/tss-lib/v3/crypto"
"github.com/bnb-chain/tss-lib/v3/tss"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/decred/dcrd/dcrec/edwards/v2"
"github.com/fystack/mpcium/pkg/mpc"
"github.com/stretchr/testify/require"
)

// goldenChainCode is a fixed chain code used to make the derivation outputs below
// fully deterministic and independent of any wallet state.
const goldenChainCode = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"

// TestCKDGoldenVectors pins the exact compressed child public keys produced by
// mpc.CKD.Derive for a fixed master key (curve generator G), chain code and set
// of BIP32 paths.
//
// Why this test exists:
// Child wallet addresses are derived deterministically from the master public
// key + chain code via tss-lib's CKD. A change in the tss-lib CKD algorithm
// (for example the modulo-N reduction of IL that was introduced in the v2->v3
// bump for Edwards curves) silently changes every derived address, which would
// make funds sent to previously-advertised addresses unspendable. These golden
// vectors were captured against github.com/fystack/tss-lib/v3 v3.0.1. If a
// future dependency bump changes any value here, this test MUST fail so the
// address-compatibility impact is reviewed explicitly rather than shipped
// silently.
func TestCKDGoldenVectors(t *testing.T) {
ckd, err := mpc.NewCKDFromHex(goldenChainCode)
require.NoError(t, err)

t.Run("secp256k1", func(t *testing.T) {
s := btcec.S256()
master, err := tsscrypto.NewECPoint(s, s.Params().Gx, s.Params().Gy)
require.NoError(t, err)

cases := map[string][]uint32{
"0250390820cfe4ddbba5f230b99288b194177e928896802d5b3a745339ed55805f": {44, 60, 0, 0, 0},
"02c8c491ebdaa1b7576cc3b72c457dad089e954a45f0e2d1b4006600cd72085194": {44, 60, 0, 0, 7},
}
for want, path := range cases {
_, ek, err := ckd.Derive("golden-secp", master, path, tss.S256())
require.NoErrorf(t, err, "derive path %v", path)
got := hex.EncodeToString(serializeCompressed(ek.PublicKey.X, ek.PublicKey.Y))
require.Equalf(t, want, got, "secp256k1 child pubkey drift at path %v", path)
}
})

t.Run("ed25519", func(t *testing.T) {
e := edwards.Edwards()
master, err := tsscrypto.NewECPoint(e, e.Params().Gx, e.Params().Gy)
require.NoError(t, err)

cases := map[string][]uint32{
"cf7d5569333be69b5488e36dd2ee07cd7f4b068a287638d02a1958cd64011a64": {44, 501, 0, 0},
"1b36b2acad34ac48134cd6f1fce6e1e9be975e6f33dfc39888aaee23e4918d6c": {44, 501, 7, 0},
}
for want, path := range cases {
_, ek, err := ckd.Derive("golden-eddsa", master, path, tss.Edwards())
require.NoErrorf(t, err, "derive path %v", path)
pk := edwards.PublicKey{Curve: e, X: ek.PublicKey.X, Y: ek.PublicKey.Y}
got := hex.EncodeToString(pk.SerializeCompressed())
require.Equalf(t, want, got, "ed25519 child pubkey drift at path %v", path)
}
})
}
2 changes: 1 addition & 1 deletion pkg/identity/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"syscall"

"filippo.io/age"
"github.com/bnb-chain/tss-lib/v2/tss"
"github.com/bnb-chain/tss-lib/v3/tss"
"golang.org/x/term"

"github.com/fystack/mpcium/pkg/common/pathutil"
Expand Down
34 changes: 21 additions & 13 deletions pkg/mpc/ckd.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package mpc

import (
"crypto/ecdsa"
"crypto/elliptic"
"encoding/hex"
"errors"
"fmt"
"math/big"

"github.com/bnb-chain/tss-lib/v2/crypto"
"github.com/bnb-chain/tss-lib/v2/crypto/ckd"
ecdsaKeygen "github.com/bnb-chain/tss-lib/v2/ecdsa/keygen"
eddsaKeygen "github.com/bnb-chain/tss-lib/v2/eddsa/keygen"
"github.com/bnb-chain/tss-lib/v3/crypto"
"github.com/bnb-chain/tss-lib/v3/crypto/ckd"
ecdsaKeygen "github.com/bnb-chain/tss-lib/v3/ecdsa/keygen"
eddsaKeygen "github.com/bnb-chain/tss-lib/v3/eddsa/keygen"
"github.com/btcsuite/btcd/chaincfg"
)

Expand Down Expand Up @@ -69,7 +70,12 @@ func (c *CKD) Derive(walletID string, masterPub *crypto.ECPoint, path []uint32,
func (c *CKD) derivingPubkeyFromPath(masterPub *crypto.ECPoint, chainCode []byte, path []uint32, ec elliptic.Curve) (*big.Int, *ckd.ExtendedKey, error) {
net := &chaincfg.MainNetParams
parent := &ckd.ExtendedKey{
PublicKey: masterPub,
// tss-lib v3 changed ExtendedKey.PublicKey from *crypto.ECPoint to ecdsa.PublicKey.
PublicKey: ecdsa.PublicKey{
Curve: masterPub.Curve(),
X: masterPub.X(),
Y: masterPub.Y(),
},
Depth: 0,
ChildIndex: 0,
ChainCode: chainCode,
Expand All @@ -85,15 +91,16 @@ func (c *CKD) derivingPubkeyFromPath(masterPub *crypto.ECPoint, chainCode []byte
}

// ECDSAUpdateSinglePublicKeyAndAdjustBigXj updates ECDSA public key and BigXj.
func (c *CKD) ECDSAUpdateSinglePublicKeyAndAdjustBigXj(delta *big.Int, key *ecdsaKeygen.LocalPartySaveData, childPk *crypto.ECPoint, ec elliptic.Curve) error {
func (c *CKD) ECDSAUpdateSinglePublicKeyAndAdjustBigXj(delta *big.Int, key *ecdsaKeygen.LocalPartySaveData, childPk ecdsa.PublicKey, ec elliptic.Curve) error {
if key == nil {
return ErrNilKey
}
if childPk == nil {
return ErrNilPoint
childPoint, err := crypto.NewECPoint(ec, childPk.X, childPk.Y)
if err != nil {
return fmt.Errorf("invalid child public key: %w", err)
}
gDelta := crypto.ScalarBaseMult(ec, delta)
key.ECDSAPub = childPk
key.ECDSAPub = childPoint
for i := range key.BigXj {
updated, err := key.BigXj[i].Add(gDelta)
if err != nil {
Expand All @@ -105,15 +112,16 @@ func (c *CKD) ECDSAUpdateSinglePublicKeyAndAdjustBigXj(delta *big.Int, key *ecds
}

// EDDSAUpdateSinglePublicKeyAndAdjustBigXj updates EdDSA public key and BigXj.
func (c *CKD) EDDSAUpdateSinglePublicKeyAndAdjustBigXj(delta *big.Int, key *eddsaKeygen.LocalPartySaveData, childPk *crypto.ECPoint, ec elliptic.Curve) error {
func (c *CKD) EDDSAUpdateSinglePublicKeyAndAdjustBigXj(delta *big.Int, key *eddsaKeygen.LocalPartySaveData, childPk ecdsa.PublicKey, ec elliptic.Curve) error {
if key == nil {
return ErrNilKey
}
if childPk == nil {
return ErrNilPoint
childPoint, err := crypto.NewECPoint(ec, childPk.X, childPk.Y)
if err != nil {
return fmt.Errorf("invalid child public key: %w", err)
}
gDelta := crypto.ScalarBaseMult(ec, delta)
key.EDDSAPub = childPk
key.EDDSAPub = childPoint
for i := range key.BigXj {
updated, err := key.BigXj[i].Add(gDelta)
if err != nil {
Expand Down
96 changes: 96 additions & 0 deletions pkg/mpc/ckd_update_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package mpc

import (
"crypto/ecdsa"
"math/big"
"testing"

"github.com/bnb-chain/tss-lib/v3/crypto"
ecdsaKeygen "github.com/bnb-chain/tss-lib/v3/ecdsa/keygen"
eddsaKeygen "github.com/bnb-chain/tss-lib/v3/eddsa/keygen"
"github.com/bnb-chain/tss-lib/v3/tss"
"github.com/stretchr/testify/require"
)

// These tests lock the behaviour of the CKD "update public key + adjust BigXj"
// helpers after the tss-lib v2 -> v3 migration, where ckd.ExtendedKey.PublicKey
// changed from *crypto.ECPoint to ecdsa.PublicKey and the helpers now accept an
// ecdsa.PublicKey child key. They verify the two invariants signing relies on:
// 1. the wallet public key is replaced by the derived child public key, and
// 2. every BigXj share point is shifted by delta*G,
// so a signature produced with the adjusted shares verifies against the child key.

func TestECDSAUpdateSinglePublicKeyAndAdjustBigXj(t *testing.T) {
ec := tss.S256()
c := &CKD{}

// Arbitrary starting share points: BigXj = [G, 2G].
bigX0 := crypto.ScalarBaseMult(ec, big.NewInt(1))
bigX1 := crypto.ScalarBaseMult(ec, big.NewInt(2))
key := &ecdsaKeygen.LocalPartySaveData{}
key.BigXj = []*crypto.ECPoint{bigX0, bigX1}
key.ECDSAPub = crypto.ScalarBaseMult(ec, big.NewInt(9))

delta := big.NewInt(123456789)
gDelta := crypto.ScalarBaseMult(ec, delta)

// child public key expressed as ecdsa.PublicKey, mirroring ckd.ExtendedKey in v3.
childPoint := crypto.ScalarBaseMult(ec, big.NewInt(777))
childPk := ecdsa.PublicKey{Curve: ec, X: childPoint.X(), Y: childPoint.Y()}

err := c.ECDSAUpdateSinglePublicKeyAndAdjustBigXj(delta, key, childPk, ec)
require.NoError(t, err)

require.True(t, key.ECDSAPub.Equals(childPoint), "ECDSAPub must equal the child key")

wantX0, err := bigX0.Add(gDelta)
require.NoError(t, err)
wantX1, err := bigX1.Add(gDelta)
require.NoError(t, err)
require.True(t, key.BigXj[0].Equals(wantX0), "BigXj[0] must be shifted by delta*G")
require.True(t, key.BigXj[1].Equals(wantX1), "BigXj[1] must be shifted by delta*G")
}

func TestEDDSAUpdateSinglePublicKeyAndAdjustBigXj(t *testing.T) {
ec := tss.Edwards()
c := &CKD{}

bigX0 := crypto.ScalarBaseMult(ec, big.NewInt(3))
bigX1 := crypto.ScalarBaseMult(ec, big.NewInt(5))
key := &eddsaKeygen.LocalPartySaveData{}
key.BigXj = []*crypto.ECPoint{bigX0, bigX1}
key.EDDSAPub = crypto.ScalarBaseMult(ec, big.NewInt(11))

delta := big.NewInt(424242)
gDelta := crypto.ScalarBaseMult(ec, delta)

childPoint := crypto.ScalarBaseMult(ec, big.NewInt(88))
childPk := ecdsa.PublicKey{Curve: ec, X: childPoint.X(), Y: childPoint.Y()}

err := c.EDDSAUpdateSinglePublicKeyAndAdjustBigXj(delta, key, childPk, ec)
require.NoError(t, err)

require.True(t, key.EDDSAPub.Equals(childPoint), "EDDSAPub must equal the child key")

wantX0, err := bigX0.Add(gDelta)
require.NoError(t, err)
wantX1, err := bigX1.Add(gDelta)
require.NoError(t, err)
require.True(t, key.BigXj[0].Equals(wantX0), "BigXj[0] must be shifted by delta*G")
require.True(t, key.BigXj[1].Equals(wantX1), "BigXj[1] must be shifted by delta*G")
}

// TestUpdateRejectsInvalidChildKey ensures a child key that is not on the curve
// is rejected rather than silently corrupting the stored share.
func TestUpdateRejectsInvalidChildKey(t *testing.T) {
ec := tss.S256()
c := &CKD{}
key := &ecdsaKeygen.LocalPartySaveData{}
key.BigXj = []*crypto.ECPoint{crypto.ScalarBaseMult(ec, big.NewInt(1))}
key.ECDSAPub = crypto.ScalarBaseMult(ec, big.NewInt(1))

// (2, 2) is not a point on secp256k1.
bad := ecdsa.PublicKey{Curve: ec, X: big.NewInt(2), Y: big.NewInt(2)}
err := c.ECDSAUpdateSinglePublicKeyAndAdjustBigXj(big.NewInt(1), key, bad, ec)
require.Error(t, err)
}
4 changes: 2 additions & 2 deletions pkg/mpc/ecdsa_keygen_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"encoding/json"
"fmt"

"github.com/bnb-chain/tss-lib/v2/ecdsa/keygen"
"github.com/bnb-chain/tss-lib/v2/tss"
"github.com/bnb-chain/tss-lib/v3/ecdsa/keygen"
"github.com/bnb-chain/tss-lib/v3/tss"
"github.com/fystack/mpcium/pkg/encoding"
"github.com/fystack/mpcium/pkg/identity"
"github.com/fystack/mpcium/pkg/keyinfo"
Expand Down
6 changes: 3 additions & 3 deletions pkg/mpc/ecdsa_resharing_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"encoding/json"
"fmt"

"github.com/bnb-chain/tss-lib/v2/ecdsa/keygen"
"github.com/bnb-chain/tss-lib/v2/ecdsa/resharing"
"github.com/bnb-chain/tss-lib/v2/tss"
"github.com/bnb-chain/tss-lib/v3/ecdsa/keygen"
"github.com/bnb-chain/tss-lib/v3/ecdsa/resharing"
"github.com/bnb-chain/tss-lib/v3/tss"
"github.com/fystack/mpcium/pkg/encoding"
"github.com/fystack/mpcium/pkg/identity"
"github.com/fystack/mpcium/pkg/keyinfo"
Expand Down
Loading
Loading