From 8746d9877eb57fa574fa70717d0424529c90f231 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 8 Nov 2022 17:59:59 +0300 Subject: [PATCH] keys: move from btcd/btcec to decred/secp256k1 package There is a security issue found in github.com/btcsuite/btcd that we don't care about (we're only using 256k1 implementation), but GitHub complains about it. We could update to github.com/btcsuite/btcd/btcec/v2, but it's now just a thin wrapper over github.com/decred/dcrd/dcrec/secp256k1/v4, so we better use it directly. --- go.mod | 4 +-- go.sum | 9 +++-- pkg/core/native/crypto.go | 4 +-- pkg/crypto/keys/private_key.go | 4 +-- pkg/crypto/keys/publickey.go | 4 +-- pkg/crypto/keys/sign_verify_test.go | 53 +++++++++++------------------ 6 files changed, 35 insertions(+), 43 deletions(-) diff --git a/go.mod b/go.mod index 308c6a647..b0296ed26 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,10 @@ module github.com/nspcc-dev/neo-go require ( - github.com/btcsuite/btcd v0.22.0-beta github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e github.com/coreos/go-semver v0.3.0 github.com/davecgh/go-spew v1.1.1 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/google/uuid v1.2.0 github.com/gorilla/websocket v1.4.2 github.com/hashicorp/golang-lru v0.5.4 @@ -19,7 +19,7 @@ require ( github.com/pierrec/lz4 v2.6.1+incompatible github.com/pmezard/go-difflib v1.0.0 github.com/prometheus/client_golang v1.13.0 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.8.0 github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 github.com/twmb/murmur3 v1.1.5 github.com/urfave/cli v1.22.5 diff --git a/go.sum b/go.sum index c20e8a758..16af10655 100644 --- a/go.sum +++ b/go.sum @@ -58,7 +58,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -94,6 +93,9 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -341,12 +343,15 @@ github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0b github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs= github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= diff --git a/pkg/core/native/crypto.go b/pkg/core/native/crypto.go index 8738a3a21..0228bc9cc 100644 --- a/pkg/core/native/crypto.go +++ b/pkg/core/native/crypto.go @@ -6,7 +6,7 @@ import ( "errors" "fmt" - "github.com/btcsuite/btcd/btcec" + "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" @@ -129,7 +129,7 @@ func curveFromStackitem(si stackitem.Item) (elliptic.Curve, error) { c := curve.Int64() switch c { case int64(Secp256k1): - return btcec.S256(), nil + return secp256k1.S256(), nil case int64(Secp256r1): return elliptic.P256(), nil default: diff --git a/pkg/crypto/keys/private_key.go b/pkg/crypto/keys/private_key.go index 8facca0d9..bf32ff8af 100644 --- a/pkg/crypto/keys/private_key.go +++ b/pkg/crypto/keys/private_key.go @@ -10,7 +10,7 @@ import ( "fmt" "math/big" - "github.com/btcsuite/btcd/btcec" + "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util/slice" @@ -30,7 +30,7 @@ func NewPrivateKey() (*PrivateKey, error) { // NewSecp256k1PrivateKey creates a new random Secp256k1 private key. func NewSecp256k1PrivateKey() (*PrivateKey, error) { - return newPrivateKeyOnCurve(btcec.S256()) + return newPrivateKeyOnCurve(secp256k1.S256()) } // newPrivateKeyOnCurve creates a new random private key using curve c. diff --git a/pkg/crypto/keys/publickey.go b/pkg/crypto/keys/publickey.go index 49bfcc02f..674ca8e76 100644 --- a/pkg/crypto/keys/publickey.go +++ b/pkg/crypto/keys/publickey.go @@ -10,7 +10,7 @@ import ( "fmt" "math/big" - "github.com/btcsuite/btcd/btcec" + "github.com/decred/dcrd/dcrec/secp256k1/v4" lru "github.com/hashicorp/golang-lru" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -204,7 +204,7 @@ func NewPublicKeyFromASN1(data []byte) (*PublicKey, error) { func decodeCompressedY(x *big.Int, ylsb uint, curve elliptic.Curve) (*big.Int, error) { var a *big.Int switch curve.(type) { - case *btcec.KoblitzCurve: + case *secp256k1.KoblitzCurve: a = big0 default: a = big3 diff --git a/pkg/crypto/keys/sign_verify_test.go b/pkg/crypto/keys/sign_verify_test.go index 7e0b8b217..20677e457 100644 --- a/pkg/crypto/keys/sign_verify_test.go +++ b/pkg/crypto/keys/sign_verify_test.go @@ -5,7 +5,7 @@ import ( "math/big" "testing" - "github.com/btcsuite/btcd/btcec" + "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -17,26 +17,25 @@ func TestIssue1223(t *testing.T) { x.SetString("56810139335762307690884151098712528235297095596167964448512639328424930082240", 10) y.SetString("108055740278314806025442297642651169427004858252141003070998851291610422839293", 10) - privateKey := &btcec.PrivateKey{ - PublicKey: ecdsa.PublicKey{ - Curve: btcec.S256(), - X: &x, - Y: &y, + privateKey := PrivateKey{ + PrivateKey: ecdsa.PrivateKey{ + PublicKey: ecdsa.PublicKey{ + Curve: secp256k1.S256(), + X: &x, + Y: &y, + }, + D: &d, }, - D: &d, } pubKey := PublicKey(ecdsa.PublicKey{ - Curve: btcec.S256(), + Curve: secp256k1.S256(), X: privateKey.X, Y: privateKey.Y, }) hashedData := hash.Sha256([]byte("sample")) - signature, err := privateKey.Sign(hashedData.BytesBE()) - require.NoError(t, err) - - signedData := getSignatureSlice(privateKey.Curve, signature.R, signature.S) - require.True(t, pubKey.Verify(signedData, hashedData.BytesBE())) + signature := privateKey.SignHash(hashedData) + require.True(t, pubKey.Verify(signature, hashedData.BytesBE())) } func TestPubKeyVerify(t *testing.T) { @@ -60,19 +59,13 @@ func TestPubKeyVerify(t *testing.T) { }) t.Run("Secp256k1", func(t *testing.T) { - privateKey, err := btcec.NewPrivateKey(btcec.S256()) + privateKey, err := NewSecp256k1PrivateKey() assert.Nil(t, err) - signature, err := privateKey.Sign(hashedData.BytesBE()) - require.NoError(t, err) - signedData := getSignatureSlice(privateKey.Curve, signature.R, signature.S) - pubKey := PublicKey(ecdsa.PublicKey{ - Curve: btcec.S256(), - X: privateKey.X, - Y: privateKey.Y, - }) + signedData := privateKey.SignHash(hashedData) + pubKey := privateKey.PublicKey() require.True(t, pubKey.Verify(signedData, hashedData.BytesBE())) - pubKey = PublicKey{} + pubKey = &PublicKey{} assert.False(t, pubKey.Verify(signedData, hashedData.BytesBE())) }) } @@ -94,19 +87,13 @@ func TestWrongPubKey(t *testing.T) { }) t.Run("Secp256k1", func(t *testing.T) { - privateKey, err := btcec.NewPrivateKey(btcec.S256()) + privateKey, err := NewSecp256k1PrivateKey() assert.Nil(t, err) - signature, err := privateKey.Sign(hashedData.BytesBE()) - assert.Nil(t, err) - signedData := getSignatureSlice(privateKey.Curve, signature.R, signature.S) + signedData := privateKey.SignHash(hashedData) - secondPrivKey, err := btcec.NewPrivateKey(btcec.S256()) + secondPrivKey, err := NewSecp256k1PrivateKey() assert.Nil(t, err) - wrongPubKey := PublicKey(ecdsa.PublicKey{ - Curve: btcec.S256(), - X: secondPrivKey.X, - Y: secondPrivKey.Y, - }) + wrongPubKey := secondPrivKey.PublicKey() assert.False(t, wrongPubKey.Verify(signedData, hashedData.BytesBE())) })