From 76fdbea33120d25a9e15b07b5742a814810ef48e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 25 Jul 2020 10:56:58 +0300 Subject: [PATCH 1/3] keys: fix failing Secp256k1 test Pad R and S when computing signature. Fix #1223. --- pkg/crypto/keys/private_key.go | 5 ++++- pkg/crypto/keys/sign_verify_test.go | 33 +++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/pkg/crypto/keys/private_key.go b/pkg/crypto/keys/private_key.go index 02f23256b..2771b80d7 100644 --- a/pkg/crypto/keys/private_key.go +++ b/pkg/crypto/keys/private_key.go @@ -136,8 +136,11 @@ func (p *PrivateKey) Sign(data []byte) []byte { ) r, s := rfc6979.SignECDSA(privateKey, digest[:], sha256.New) + return getSignatureSlice(privateKey.Curve, r, s) +} - params := privateKey.Curve.Params() +func getSignatureSlice(curve elliptic.Curve, r, s *big.Int) []byte { + params := curve.Params() curveOrderByteSize := params.P.BitLen() / 8 rBytes, sBytes := r.Bytes(), s.Bytes() signature := make([]byte, curveOrderByteSize*2) diff --git a/pkg/crypto/keys/sign_verify_test.go b/pkg/crypto/keys/sign_verify_test.go index b78df4fac..405a99c9d 100644 --- a/pkg/crypto/keys/sign_verify_test.go +++ b/pkg/crypto/keys/sign_verify_test.go @@ -2,6 +2,7 @@ package keys import ( "crypto/ecdsa" + "math/big" "testing" "github.com/btcsuite/btcd/btcec" @@ -10,6 +11,34 @@ import ( "github.com/stretchr/testify/require" ) +func TestIssue1223(t *testing.T) { + var d, x, y big.Int + d.SetString("75066030006596498716801752450216843918658392116070031536027203512060270094427", 10) + x.SetString("56810139335762307690884151098712528235297095596167964448512639328424930082240", 10) + y.SetString("108055740278314806025442297642651169427004858252141003070998851291610422839293", 10) + + privateKey := &btcec.PrivateKey{ + PublicKey: ecdsa.PublicKey{ + Curve: btcec.S256(), + X: &x, + Y: &y, + }, + D: &d, + } + pubKey := PublicKey(ecdsa.PublicKey{ + Curve: btcec.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())) +} + func TestPubKeyVerify(t *testing.T) { var data = []byte("sample") hashedData := hash.Sha256(data) @@ -32,7 +61,7 @@ func TestPubKeyVerify(t *testing.T) { assert.Nil(t, err) signature, err := privateKey.Sign(hashedData.BytesBE()) require.NoError(t, err) - signedData := append(signature.R.Bytes(), signature.S.Bytes()...) + signedData := getSignatureSlice(privateKey.Curve, signature.R, signature.S) pubKey := PublicKey(ecdsa.PublicKey{ Curve: btcec.S256(), X: privateKey.X, @@ -66,7 +95,7 @@ func TestWrongPubKey(t *testing.T) { assert.Nil(t, err) signature, err := privateKey.Sign(hashedData.BytesBE()) assert.Nil(t, err) - signedData := append(signature.R.Bytes(), signature.S.Bytes()...) + signedData := getSignatureSlice(privateKey.Curve, signature.R, signature.S) secondPrivKey, err := btcec.NewPrivateKey(btcec.S256()) assert.Nil(t, err) From 83e53fab247119c0823b2d087bbb9c93b358ab77 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 25 Jul 2020 11:50:03 +0300 Subject: [PATCH 2/3] core/test: ensure public key is invalid in test When providing public key as a subslice, it still can be decoded as a valid key, thus interop will not return an error but rather push `false` on stack. This test is about providing invalid key, so ensure this via setting invalid prefix. --- pkg/core/interop_neo_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/core/interop_neo_test.go b/pkg/core/interop_neo_test.go index 2336fed8a..525b04942 100644 --- a/pkg/core/interop_neo_test.go +++ b/pkg/core/interop_neo_test.go @@ -210,7 +210,7 @@ func TestECDSAVerify(t *testing.T) { t.Run("invalid public key", func(t *testing.T) { sign := priv.Sign(msg) pub := priv.PublicKey().Bytes() - pub = pub[10:] + pub[0] = 0xFF // invalid prefix runCase(t, true, false, sign, pub, msg) }) } From 8931c9a794ab053fbcea082c414030a59ea9154f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 25 Jul 2020 12:16:56 +0300 Subject: [PATCH 3/3] core/interop: increase coverate for crypto interops --- pkg/core/interop/crypto/ecdsa_test.go | 18 ++++++++++++++---- pkg/core/interop_neo_test.go | 6 ++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/pkg/core/interop/crypto/ecdsa_test.go b/pkg/core/interop/crypto/ecdsa_test.go index 4261d0014..4dd735e87 100644 --- a/pkg/core/interop/crypto/ecdsa_test.go +++ b/pkg/core/interop/crypto/ecdsa_test.go @@ -97,16 +97,26 @@ func TestCHECKMULTISIGGood(t *testing.T) { t.Run("12_9", func(t *testing.T) { testCHECKMULTISIGGood(t, 12, []int{0, 1, 4, 5, 6, 7, 8, 9}) }) } -func testCHECKMULTISIGBad(t *testing.T, n int, ik, is []int) { +func testCHECKMULTISIGBad(t *testing.T, isErr bool, n int, ik, is []int) { v := initCHECKMULTISIGVM(t, n, ik, is) + if isErr { + require.Error(t, v.Run()) + return + } require.NoError(t, v.Run()) assert.Equal(t, 1, v.Estack().Len()) assert.False(t, v.Estack().Pop().Bool()) } func TestCHECKMULTISIGBad(t *testing.T) { - t.Run("1_1 wrong signature", func(t *testing.T) { testCHECKMULTISIGBad(t, 2, []int{0}, []int{1}) }) - t.Run("3_2 wrong order", func(t *testing.T) { testCHECKMULTISIGBad(t, 3, []int{0, 2}, []int{2, 0}) }) - t.Run("3_2 duplicate sig", func(t *testing.T) { testCHECKMULTISIGBad(t, 3, nil, []int{0, 0}) }) + t.Run("1_1 wrong signature", func(t *testing.T) { testCHECKMULTISIGBad(t, false, 2, []int{0}, []int{1}) }) + t.Run("3_2 wrong order", func(t *testing.T) { testCHECKMULTISIGBad(t, false, 3, []int{0, 2}, []int{2, 0}) }) + t.Run("3_2 duplicate sig", func(t *testing.T) { testCHECKMULTISIGBad(t, false, 3, nil, []int{0, 0}) }) + t.Run("1_2 too many signatures", func(t *testing.T) { testCHECKMULTISIGBad(t, true, 2, []int{0}, []int{0, 1}) }) + t.Run("gas limit exceeded", func(t *testing.T) { + v := initCHECKMULTISIGVM(t, 1, []int{0}, []int{0}) + v.GasLimit = ECDSAVerifyPrice - 1 + require.Error(t, v.Run()) + }) } diff --git a/pkg/core/interop_neo_test.go b/pkg/core/interop_neo_test.go index 525b04942..92cd8fcf8 100644 --- a/pkg/core/interop_neo_test.go +++ b/pkg/core/interop_neo_test.go @@ -213,6 +213,12 @@ func TestECDSAVerify(t *testing.T) { pub[0] = 0xFF // invalid prefix runCase(t, true, false, sign, pub, msg) }) + + t.Run("invalid message", func(t *testing.T) { + sign := priv.Sign(msg) + runCase(t, false, false, sign, priv.PublicKey().Bytes(), + stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray(msg)})) + }) } func TestRuntimeEncode(t *testing.T) {