diff --git a/crypto/ckd/child_key_derivation.go b/crypto/ckd/child_key_derivation.go index 6d188d3a0..3632f301e 100644 --- a/crypto/ckd/child_key_derivation.go +++ b/crypto/ckd/child_key_derivation.go @@ -16,8 +16,8 @@ import ( "github.com/bnb-chain/tss-lib/common" "github.com/bnb-chain/tss-lib/crypto" - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcutil/base58" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil/base58" "golang.org/x/crypto/ripemd160" ) @@ -105,14 +105,15 @@ func NewExtendedKeyFromString(key string, curve elliptic.Curve) (*ExtendedKey, e var pubKey ecdsa.PublicKey - if c, ok := curve.(*btcec.KoblitzCurve); ok { + if _, ok := curve.(*btcec.KoblitzCurve); ok { // Ensure the public key parses correctly and is actually on the // secp256k1 curve. - pk, err := btcec.ParsePubKey(keyData, c) + pk, err := btcec.ParsePubKey(keyData) if err != nil { return nil, err } - pubKey = ecdsa.PublicKey(*pk) + pubKey = *pk.ToECDSA() + pubKey.Curve = curve } else { px, py := elliptic.Unmarshal(curve, keyData) pubKey = ecdsa.PublicKey{ diff --git a/crypto/ckd/child_key_derivation_test.go b/crypto/ckd/child_key_derivation_test.go index a065b9d97..0fe661392 100644 --- a/crypto/ckd/child_key_derivation_test.go +++ b/crypto/ckd/child_key_derivation_test.go @@ -10,9 +10,41 @@ import ( "testing" . "github.com/bnb-chain/tss-lib/crypto/ckd" - "github.com/btcsuite/btcd/btcec" + "github.com/bnb-chain/tss-lib/tss" + "github.com/btcsuite/btcd/btcec/v2" ) +func TestLegacyPublicDerivationHierarchy(t *testing.T) { + // Captured with btcec at c26ffa870fd8. Pin both the serialized xpub and + // the accumulated scalar used to adjust existing signing shares. + const master = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8" + const wantChild = "xpub6CYmVEgeUykCausT5DuGF88T5ygofv63uKA287sVoASqgavVhNXxVWCrGQQReXBjyMGkURetqftCVhMrAzLoCUcbP46o4sibtt3LisHMKkC" + const wantDelta = "5cf748ee8bf3158bd5f642c0cab22fbf9e3148181497b3e85386ebe4d4819620" + curve := tss.S256() + root, err := NewExtendedKeyFromString(master, curve) + if err != nil { + t.Fatal(err) + } + if root.PublicKey.Curve != curve || !curve.IsOnCurve(root.X, root.Y) { + t.Fatal("parsed key did not preserve the ECDSA public key contract") + } + curveCopy := *btcec.S256() + withCurveCopy, err := NewExtendedKeyFromString(master, &curveCopy) + if err != nil { + t.Fatal(err) + } + if withCurveCopy.Curve != &curveCopy || withCurveCopy.String() != master { + t.Fatal("parsed key did not retain the supplied curve instance") + } + delta, child, err := DeriveChildKeyFromHierarchy([]uint32{12, 209, 3}, root, curve.Params().N, curve) + if err != nil { + t.Fatal(err) + } + if child.String() != wantChild || delta.Text(16) != wantDelta { + t.Fatalf("hierarchy differs from legacy output: child %s, delta %x", child, delta) + } +} + 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]. diff --git a/crypto/ecpoint_compatibility_test.go b/crypto/ecpoint_compatibility_test.go new file mode 100644 index 000000000..ed54b5eb0 --- /dev/null +++ b/crypto/ecpoint_compatibility_test.go @@ -0,0 +1,64 @@ +package crypto_test + +import ( + "encoding/hex" + "encoding/json" + "math/big" + "testing" + + "github.com/bnb-chain/tss-lib/crypto" + "github.com/bnb-chain/tss-lib/tss" +) + +// These ordinary public-point outputs were captured with the legacy btcec +// dependency at c26ffa870fd8 before migrating to btcec/v2. +func TestSecp256k1LegacyPointCompatibility(t *testing.T) { + curve := tss.S256() + point := crypto.ScalarBaseMult(curve, big.NewInt(42)) + added, err := point.Add(crypto.ScalarBaseMult(curve, big.NewInt(17))) + if err != nil { + t.Fatal(err) + } + for _, test := range []struct { + name string + point *crypto.ECPoint + x, y string + }{ + {"base multiply", point, "fe8d1eb1bcb3432b1db5833ff5f2226d9cb5e65cee430558c18ed3a3c86ce1af", "7b158f244cd0de2134ac7c1d371cffbfae4db40801a2572e531c573cda9b5b4"}, + {"add", added, "7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435", "91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61"}, + {"multiply", point.ScalarMult(big.NewInt(17)), "13a5fa6920629fd9f14541b803f64baa67f043fbc883ea787722de0f68d8fbe5", "76cd800492f816f4b7b8c2c55d3a4022d9498094932406fc6d2159c7eb06ac70"}, + } { + t.Run(test.name, func(t *testing.T) { + if test.point == nil || test.point.X().Text(16) != test.x || test.point.Y().Text(16) != test.y { + t.Fatal("point differs from legacy output") + } + pub := test.point.ToECDSAPubKey() + if pub.Curve != curve || pub.X.Cmp(test.point.X()) != 0 || pub.Y.Cmp(test.point.Y()) != 0 { + t.Fatal("ECDSA public key conversion changed") + } + }) + } + + const legacyJSON = `{"Curve":"secp256k1","Coords":[115136800820456833737994126771386015026287095034625623644186278108926690779567,3479535755779840016334846590594739014278212596066547564422106861430200972724]}` + const legacyGob = "2100000002fe8d1eb1bcb3432b1db5833ff5f2226d9cb5e65cee430558c18ed3a3c86ce1af210000000207b158f244cd0de2134ac7c1d371cffbfae4db40801a2572e531c573cda9b5b4" + encoded, err := json.Marshal(point) + if err != nil || string(encoded) != legacyJSON { + t.Fatalf("JSON differs from legacy output: %s, %v", encoded, err) + } + var fromJSON crypto.ECPoint + if err := json.Unmarshal([]byte(legacyJSON), &fromJSON); err != nil || !point.Equals(&fromJSON) { + t.Fatalf("legacy JSON could not be restored: %v", err) + } + encoded, err = point.GobEncode() + if err != nil || hex.EncodeToString(encoded) != legacyGob { + t.Fatalf("Gob differs from legacy output: %x, %v", encoded, err) + } + legacyBytes, err := hex.DecodeString(legacyGob) + if err != nil { + t.Fatal(err) + } + var fromGob crypto.ECPoint + if err := fromGob.GobDecode(legacyBytes); err != nil || !point.Equals(&fromGob) { + t.Fatalf("legacy Gob could not be restored: %v", err) + } +} diff --git a/crypto/ecpoint_test.go b/crypto/ecpoint_test.go index 3d02eda63..8db55c4b5 100644 --- a/crypto/ecpoint_test.go +++ b/crypto/ecpoint_test.go @@ -14,7 +14,7 @@ import ( "reflect" "testing" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/stretchr/testify/assert" . "github.com/bnb-chain/tss-lib/crypto" @@ -146,10 +146,10 @@ func TestS256EcpointJsonSerialization(t *testing.T) { pubKeyBytes, err := hex.DecodeString("03935336acb03b2b801d8f8ac5e92c56c4f6e93319901fdfffba9d340a874e2879") assert.NoError(t, err) - pbk, err := btcec.ParsePubKey(pubKeyBytes, btcec.S256()) + pbk, err := btcec.ParsePubKey(pubKeyBytes) assert.NoError(t, err) - point, err := NewECPoint(ec, pbk.X, pbk.Y) + point, err := NewECPoint(ec, pbk.X(), pbk.Y()) assert.NoError(t, err) bz, err := json.Marshal(point) assert.NoError(t, err) diff --git a/ecdsa/keygen/save_data_compatibility_test.go b/ecdsa/keygen/save_data_compatibility_test.go new file mode 100644 index 000000000..3ae85b718 --- /dev/null +++ b/ecdsa/keygen/save_data_compatibility_test.go @@ -0,0 +1,69 @@ +package keygen_test + +import ( + "bytes" + "encoding/gob" + "encoding/hex" + "encoding/json" + "io/ioutil" + "math/big" + "testing" + + "github.com/bnb-chain/tss-lib/crypto" + "github.com/bnb-chain/tss-lib/ecdsa/keygen" + "github.com/bnb-chain/tss-lib/tss" +) + +func TestLegacySaveDataSerialization(t *testing.T) { + point := crypto.ScalarBaseMult(tss.S256(), big.NewInt(42)) + want := keygen.LocalPartySaveData{ + Ks: []*big.Int{big.NewInt(1)}, BigXj: []*crypto.ECPoint{point}, ECDSAPub: point, + } + legacyJSON, err := ioutil.ReadFile("testdata/save_data_legacy_btcec.json") + if err != nil { + t.Fatal(err) + } + encoded, err := json.Marshal(want) + if err != nil || !bytes.Equal(encoded, bytes.TrimSpace(legacyJSON)) { + t.Fatalf("save-data JSON differs from legacy output: %v", err) + } + legacyHex, err := ioutil.ReadFile("testdata/save_data_legacy_btcec.gob.hex") + if err != nil { + t.Fatal(err) + } + legacyGob, err := hex.DecodeString(string(bytes.TrimSpace(legacyHex))) + if err != nil { + t.Fatal(err) + } + for _, format := range []string{"json", "gob"} { + t.Run(format, func(t *testing.T) { + var restored keygen.LocalPartySaveData + var err error + if format == "json" { + err = json.Unmarshal(legacyJSON, &restored) + } else { + err = gob.NewDecoder(bytes.NewReader(legacyGob)).Decode(&restored) + } + if err != nil { + t.Fatal(err) + } + if len(restored.Ks) != 1 || restored.Ks[0].Cmp(big.NewInt(1)) != 0 || + len(restored.BigXj) != 1 || !point.Equals(restored.BigXj[0]) || !point.Equals(restored.ECDSAPub) { + t.Fatal("restored save data differs from legacy output") + } + if !tss.SameCurve(restored.BigXj[0].Curve(), tss.S256()) || !tss.SameCurve(restored.ECDSAPub.Curve(), tss.S256()) { + t.Fatal("restored save-data points lost their curve registration") + } + if format == "gob" { + var buf bytes.Buffer + if err := gob.NewEncoder(&buf).Encode(restored); err != nil { + t.Fatal(err) + } + var roundTrip keygen.LocalPartySaveData + if err := gob.NewDecoder(&buf).Decode(&roundTrip); err != nil || !point.Equals(roundTrip.ECDSAPub) { + t.Fatalf("save-data Gob round trip failed: %v", err) + } + } + }) + } +} diff --git a/ecdsa/keygen/testdata/README.md b/ecdsa/keygen/testdata/README.md new file mode 100644 index 000000000..517b065c6 --- /dev/null +++ b/ecdsa/keygen/testdata/README.md @@ -0,0 +1,12 @@ +The `save_data_legacy_btcec` files contain a synthetic `LocalPartySaveData` +value encoded at commit `86bd1a3` with the original btcec dependency +`github.com/btcsuite/btcd@v0.0.0-20190629003639-c26ffa870fd8`, using Go 1.26.0. +They contain no signing secrets. The value has `Ks = [1]`, `BigXj = [42*G]`, +and `ECDSAPub = 42*G`; all other fields have their zero values. The Gob file +is hex-encoded for reviewability. + +These fixed fixtures check that the btcec/v2 migration can read previously +saved JSON and Gob data. The test also checks unchanged JSON output and a +new Gob round trip. Exact Gob stream bytes can depend on type registration +order, so only the point's custom Gob payload is compared byte for byte in +the crypto package. diff --git a/ecdsa/keygen/testdata/save_data_legacy_btcec.gob.hex b/ecdsa/keygen/testdata/save_data_legacy_btcec.gob.hex new file mode 100644 index 000000000..9da3ea10a --- /dev/null +++ b/ecdsa/keygen/testdata/save_data_legacy_btcec.gob.hex @@ -0,0 +1 @@ +ff967f030101124c6f63616c5061727479536176654461746101ff80000109010e4c6f63616c507265506172616d7301ff8200010c4c6f63616c5365637265747301ff8a0001024b7301ff8c0001074e54696c64656a01ff8c00010348316a01ff8c00010348326a01ff8c000105426967586a01ff9000010b5061696c6c696572504b7301ff92000108454344534150756201ff8e0000006eff810301010e4c6f63616c507265506172616d7301ff82000108010a5061696c6c696572534b01ff840001074e54696c64656901ff8800010348316901ff8800010348326901ff88000105416c70686101ff880001044265746101ff880001015001ff880001015101ff880000003eff830301010a507269766174654b657901ff8400010301095075626c69634b657901ff860001074c616d6264614e01ff880001045068694e01ff880000001eff85030101095075626c69634b657901ff8600010101014e01ff880000000aff87050102ff940000002fff890301010c4c6f63616c5365637265747301ff8a0001020102586901ff880001075368617265494401ff8800000019ff8b0201010a5b5d2a6269672e496e7401ff8c0001ff88000020ff8f020101115b5d2a63727970746f2e4543506f696e7401ff900001ff8e00000aff8d050102ff9600000024ff91020101155b5d2a7061696c6c6965722e5075626c69634b657901ff920001ff860000ffa5ff8001000100010102020104014a2100000002fe8d1eb1bcb3432b1db5833ff5f2226d9cb5e65cee430558c18ed3a3c86ce1af210000000207b158f244cd0de2134ac7c1d371cffbfae4db40801a2572e531c573cda9b5b4024a2100000002fe8d1eb1bcb3432b1db5833ff5f2226d9cb5e65cee430558c18ed3a3c86ce1af210000000207b158f244cd0de2134ac7c1d371cffbfae4db40801a2572e531c573cda9b5b400 diff --git a/ecdsa/keygen/testdata/save_data_legacy_btcec.json b/ecdsa/keygen/testdata/save_data_legacy_btcec.json new file mode 100644 index 000000000..5a4076a1b --- /dev/null +++ b/ecdsa/keygen/testdata/save_data_legacy_btcec.json @@ -0,0 +1 @@ +{"PaillierSK":null,"NTildei":null,"H1i":null,"H2i":null,"Alpha":null,"Beta":null,"P":null,"Q":null,"Xi":null,"ShareID":null,"Ks":[1],"NTildej":null,"H1j":null,"H2j":null,"BigXj":[{"Curve":"secp256k1","Coords":[115136800820456833737994126771386015026287095034625623644186278108926690779567,3479535755779840016334846590594739014278212596066547564422106861430200972724]}],"PaillierPKs":null,"ECDSAPub":{"Curve":"secp256k1","Coords":[115136800820456833737994126771386015026287095034625623644186278108926690779567,3479535755779840016334846590594739014278212596066547564422106861430200972724]}} diff --git a/ecdsa/signing/local_party_test.go b/ecdsa/signing/local_party_test.go index 6ecd0d919..aa6cf0bc8 100644 --- a/ecdsa/signing/local_party_test.go +++ b/ecdsa/signing/local_party_test.go @@ -17,7 +17,7 @@ import ( "sync/atomic" "testing" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/ipfs/go-log" "github.com/stretchr/testify/assert" diff --git a/go.mod b/go.mod index 0c2d09eb1..841619ca5 100644 --- a/go.mod +++ b/go.mod @@ -5,19 +5,22 @@ go 1.25.7 toolchain go1.26.8 require ( - github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8 - github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d + github.com/btcsuite/btcd v0.24.2 + github.com/btcsuite/btcd/btcec/v2 v2.2.0 + github.com/btcsuite/btcd/btcutil v1.1.5 github.com/hashicorp/go-multierror v1.0.0 github.com/ipfs/go-log v0.0.1 github.com/otiai10/primes v0.0.0-20180210170552-f6d2a1ba97c4 github.com/pkg/errors v0.8.1 - github.com/stretchr/testify v1.3.0 + github.com/stretchr/testify v1.8.4 golang.org/x/crypto v0.52.0 google.golang.org/protobuf v1.33.0 ) require ( + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/gogo/protobuf v1.2.1 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/mattn/go-colorable v0.1.2 // indirect @@ -27,4 +30,5 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc // indirect golang.org/x/sys v0.45.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 41a7351f4..823bf7256 100644 --- a/go.sum +++ b/go.sum @@ -1,26 +1,58 @@ bou.ke/monkey v1.0.1 h1:zEMLInw9xvNakzUUPjfS4Ds6jYPqCFx3m7bRmG5NH2U= bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -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/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= 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= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= @@ -29,6 +61,7 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -39,9 +72,15 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -55,27 +94,60 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= 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/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988= golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tss/curve.go b/tss/curve.go index 0b08db8b9..fbd1fcd1d 100644 --- a/tss/curve.go +++ b/tss/curve.go @@ -11,7 +11,7 @@ import ( "errors" "reflect" - s256k1 "github.com/btcsuite/btcd/btcec" + s256k1 "github.com/btcsuite/btcd/btcec/v2" ) type CurveName string @@ -78,7 +78,10 @@ func SetCurve(curve elliptic.Curve) { ec = curve } -// secp256k1 +// S256 returns the secp256k1 curve from btcec/v2. Its concrete type is an alias +// of Decred's secp256k1/v4.KoblitzCurve, not the legacy btcec.KoblitzCurve. +// Callers should use the elliptic.Curve interface; its registered name remains +// "secp256k1" for ECPoint JSON serialization. func S256() elliptic.Curve { return s256k1.S256() } diff --git a/tss/curve_test.go b/tss/curve_test.go new file mode 100644 index 000000000..23c651bc2 --- /dev/null +++ b/tss/curve_test.go @@ -0,0 +1,36 @@ +package tss + +import ( + "crypto/elliptic" + "testing" +) + +type customCurve struct{ elliptic.Curve } + +func TestCurveRegistryPreservesImplementationIdentity(t *testing.T) { + originalRegistry, originalEC := registry, ec + defer func() { registry, ec = originalRegistry, originalEC }() + registry = map[CurveName]elliptic.Curve{Secp256k1: S256()} + + if name, ok := GetCurveName(S256()); !ok || name != Secp256k1 { + t.Fatalf("default curve registered as %q, %v", name, ok) + } + custom := &customCurve{S256()} + if name, ok := GetCurveName(custom); ok { + t.Fatalf("unregistered implementation recognized as %q", name) + } + RegisterCurve("custom", custom) + if name, ok := GetCurveName(custom); !ok || name != "custom" { + t.Fatalf("custom curve registered as %q, %v", name, ok) + } + if SameCurve(custom, S256()) { + t.Fatal("different registered implementations treated as the same curve") + } + if got, ok := GetCurveByName("custom"); !ok || got != custom { + t.Fatal("custom curve implementation was not preserved") + } + SetCurve(custom) + if EC() != custom { + t.Fatal("SetCurve did not preserve the supplied implementation") + } +}