core: remove Neo.Crypto.CheckMultisigWithECDsaSecp256k1

Koblitz RIP.
This commit is contained in:
Anna Shaleva 2021-03-09 17:38:41 +03:00
parent cdaca7be3e
commit 7126637f73
7 changed files with 32 additions and 73 deletions

View file

@ -90,7 +90,6 @@ func TestSyscallExecution(t *testing.T) {
"storage.Put": {interopnames.SystemStoragePut, []string{sctx, b, b}, true}, "storage.Put": {interopnames.SystemStoragePut, []string{sctx, b, b}, true},
"storage.ConvertContextToReadOnly": {interopnames.SystemStorageAsReadOnly, []string{sctx}, false}, "storage.ConvertContextToReadOnly": {interopnames.SystemStorageAsReadOnly, []string{sctx}, false},
"crypto.ECDSASecp256r1CheckMultisig": {interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1, []string{b, pubs, sigs}, false}, "crypto.ECDSASecp256r1CheckMultisig": {interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1, []string{b, pubs, sigs}, false},
"crypto.ECDSASecp256k1CheckMultisig": {interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1, []string{b, pubs, sigs}, false},
"crypto.CheckSig": {interopnames.NeoCryptoCheckSig, []string{pub, sig}, false}, "crypto.CheckSig": {interopnames.NeoCryptoCheckSig, []string{pub, sig}, false},
} }
ic := &interop.Context{} ic := &interop.Context{}

View file

@ -5,7 +5,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/btcsuite/btcd/btcec"
"github.com/nspcc-dev/neo-go/pkg/core/fee" "github.com/nspcc-dev/neo-go/pkg/core/fee"
"github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/crypto" "github.com/nspcc-dev/neo-go/pkg/crypto"
@ -19,18 +18,6 @@ import (
// ECDSASecp256r1CheckMultisig checks multiple ECDSA signatures at once using // ECDSASecp256r1CheckMultisig checks multiple ECDSA signatures at once using
// Secp256r1 elliptic curve. // Secp256r1 elliptic curve.
func ECDSASecp256r1CheckMultisig(ic *interop.Context) error { func ECDSASecp256r1CheckMultisig(ic *interop.Context) error {
return ecdsaCheckMultisig(ic, elliptic.P256())
}
// ECDSASecp256k1CheckMultisig checks multiple ECDSA signatures at once using
// Secp256k1 elliptic curve.
func ECDSASecp256k1CheckMultisig(ic *interop.Context) error {
return ecdsaCheckMultisig(ic, btcec.S256())
}
// ecdsaCheckMultisig is internal representation of ECDSASecp256r1CheckMultisig and
// ECDSASecp256k1CheckMultisig
func ecdsaCheckMultisig(ic *interop.Context, curve elliptic.Curve) error {
hashToCheck, err := getMessageHash(ic, ic.VM.Estack().Pop().Item()) hashToCheck, err := getMessageHash(ic, ic.VM.Estack().Pop().Item())
if err != nil { if err != nil {
return err return err
@ -51,7 +38,7 @@ func ecdsaCheckMultisig(ic *interop.Context, curve elliptic.Curve) error {
if len(pkeys) < len(sigs) { if len(pkeys) < len(sigs) {
return errors.New("more signatures than there are keys") return errors.New("more signatures than there are keys")
} }
sigok := vm.CheckMultisigPar(ic.VM, curve, hashToCheck.BytesBE(), pkeys, sigs) sigok := vm.CheckMultisigPar(ic.VM, elliptic.P256(), hashToCheck.BytesBE(), pkeys, sigs)
ic.VM.Estack().PushVal(sigok) ic.VM.Estack().PushVal(sigok)
return nil return nil
} }

View file

@ -20,18 +20,14 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func initCHECKMULTISIG(isR1 bool, msg []byte, n int) ([]stackitem.Item, []stackitem.Item, map[string]*keys.PublicKey, error) { func initCHECKMULTISIG(msg []byte, n int) ([]stackitem.Item, []stackitem.Item, map[string]*keys.PublicKey, error) {
var err error var err error
keyMap := make(map[string]*keys.PublicKey) keyMap := make(map[string]*keys.PublicKey)
pkeys := make([]*keys.PrivateKey, n) pkeys := make([]*keys.PrivateKey, n)
pubs := make([]stackitem.Item, n) pubs := make([]stackitem.Item, n)
for i := range pubs { for i := range pubs {
if isR1 {
pkeys[i], err = keys.NewPrivateKey() pkeys[i], err = keys.NewPrivateKey()
} else {
pkeys[i], err = keys.NewSecp256k1PrivateKey()
}
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
@ -64,14 +60,10 @@ func subSlice(arr []stackitem.Item, indices []int) []stackitem.Item {
return result return result
} }
func initCheckMultisigVMNoArgs(isR1 bool) *vm.VM { func initCheckMultisigVMNoArgs() *vm.VM {
buf := make([]byte, 5) buf := make([]byte, 5)
buf[0] = byte(opcode.SYSCALL) buf[0] = byte(opcode.SYSCALL)
if isR1 {
binary.LittleEndian.PutUint32(buf[1:], ecdsaSecp256r1CheckMultisigID) binary.LittleEndian.PutUint32(buf[1:], ecdsaSecp256r1CheckMultisigID)
} else {
binary.LittleEndian.PutUint32(buf[1:], ecdsaSecp256k1CheckMultisigID)
}
ic := &interop.Context{Trigger: trigger.Verification} ic := &interop.Context{Trigger: trigger.Verification}
Register(ic) Register(ic)
@ -80,11 +72,11 @@ func initCheckMultisigVMNoArgs(isR1 bool) *vm.VM {
return v return v
} }
func initCHECKMULTISIGVM(t *testing.T, isR1 bool, n int, ik, is []int) *vm.VM { func initCHECKMULTISIGVM(t *testing.T, n int, ik, is []int) *vm.VM {
v := initCheckMultisigVMNoArgs(isR1) v := initCheckMultisigVMNoArgs()
msg := []byte("NEO - An Open Network For Smart Economy") msg := []byte("NEO - An Open Network For Smart Economy")
pubs, sigs, _, err := initCHECKMULTISIG(isR1, msg, n) pubs, sigs, _, err := initCHECKMULTISIG(msg, n)
require.NoError(t, err) require.NoError(t, err)
pubs = subSlice(pubs, ik) pubs = subSlice(pubs, ik)
@ -97,8 +89,8 @@ func initCHECKMULTISIGVM(t *testing.T, isR1 bool, n int, ik, is []int) *vm.VM {
return v return v
} }
func testCHECKMULTISIGGood(t *testing.T, isR1 bool, n int, is []int) { func testCHECKMULTISIGGood(t *testing.T, n int, is []int) {
v := initCHECKMULTISIGVM(t, isR1, n, nil, is) v := initCHECKMULTISIGVM(t, n, nil, is)
require.NoError(t, v.Run()) require.NoError(t, v.Run())
assert.Equal(t, 1, v.Estack().Len()) assert.Equal(t, 1, v.Estack().Len())
@ -106,25 +98,21 @@ func testCHECKMULTISIGGood(t *testing.T, isR1 bool, n int, is []int) {
} }
func TestECDSASecp256r1CheckMultisigGood(t *testing.T) { func TestECDSASecp256r1CheckMultisigGood(t *testing.T) {
testCurveCHECKMULTISIGGood(t, true) testCurveCHECKMULTISIGGood(t)
} }
func TestECDSASecp256k1CheckMultisigGood(t *testing.T) { func testCurveCHECKMULTISIGGood(t *testing.T) {
testCurveCHECKMULTISIGGood(t, false) t.Run("3_1", func(t *testing.T) { testCHECKMULTISIGGood(t, 3, []int{1}) })
t.Run("2_2", func(t *testing.T) { testCHECKMULTISIGGood(t, 2, []int{0, 1}) })
t.Run("3_3", func(t *testing.T) { testCHECKMULTISIGGood(t, 3, []int{0, 1, 2}) })
t.Run("3_2", func(t *testing.T) { testCHECKMULTISIGGood(t, 3, []int{0, 2}) })
t.Run("4_2", func(t *testing.T) { testCHECKMULTISIGGood(t, 4, []int{0, 2}) })
t.Run("10_7", func(t *testing.T) { testCHECKMULTISIGGood(t, 10, []int{2, 3, 4, 5, 6, 8, 9}) })
t.Run("12_9", func(t *testing.T) { testCHECKMULTISIGGood(t, 12, []int{0, 1, 4, 5, 6, 7, 8, 9}) })
} }
func testCurveCHECKMULTISIGGood(t *testing.T, isR1 bool) { func testCHECKMULTISIGBad(t *testing.T, isErr bool, n int, ik, is []int) {
t.Run("3_1", func(t *testing.T) { testCHECKMULTISIGGood(t, isR1, 3, []int{1}) }) v := initCHECKMULTISIGVM(t, n, ik, is)
t.Run("2_2", func(t *testing.T) { testCHECKMULTISIGGood(t, isR1, 2, []int{0, 1}) })
t.Run("3_3", func(t *testing.T) { testCHECKMULTISIGGood(t, isR1, 3, []int{0, 1, 2}) })
t.Run("3_2", func(t *testing.T) { testCHECKMULTISIGGood(t, isR1, 3, []int{0, 2}) })
t.Run("4_2", func(t *testing.T) { testCHECKMULTISIGGood(t, isR1, 4, []int{0, 2}) })
t.Run("10_7", func(t *testing.T) { testCHECKMULTISIGGood(t, isR1, 10, []int{2, 3, 4, 5, 6, 8, 9}) })
t.Run("12_9", func(t *testing.T) { testCHECKMULTISIGGood(t, isR1, 12, []int{0, 1, 4, 5, 6, 7, 8, 9}) })
}
func testCHECKMULTISIGBad(t *testing.T, isR1 bool, isErr bool, n int, ik, is []int) {
v := initCHECKMULTISIGVM(t, isR1, n, ik, is)
if isErr { if isErr {
require.Error(t, v.Run()) require.Error(t, v.Run())
@ -136,45 +124,41 @@ func testCHECKMULTISIGBad(t *testing.T, isR1 bool, isErr bool, n int, ik, is []i
} }
func TestECDSASecp256r1CheckMultisigBad(t *testing.T) { func TestECDSASecp256r1CheckMultisigBad(t *testing.T) {
testCurveCHECKMULTISIGBad(t, true) testCurveCHECKMULTISIGBad(t)
} }
func TestECDSASecp256k1CheckMultisigBad(t *testing.T) { func testCurveCHECKMULTISIGBad(t *testing.T) {
testCurveCHECKMULTISIGBad(t, false) 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}) })
func testCurveCHECKMULTISIGBad(t *testing.T, isR1 bool) { t.Run("1_2 too many signatures", func(t *testing.T) { testCHECKMULTISIGBad(t, true, 2, []int{0}, []int{0, 1}) })
t.Run("1_1 wrong signature", func(t *testing.T) { testCHECKMULTISIGBad(t, isR1, false, 2, []int{0}, []int{1}) })
t.Run("3_2 wrong order", func(t *testing.T) { testCHECKMULTISIGBad(t, isR1, false, 3, []int{0, 2}, []int{2, 0}) })
t.Run("3_2 duplicate sig", func(t *testing.T) { testCHECKMULTISIGBad(t, isR1, false, 3, nil, []int{0, 0}) })
t.Run("1_2 too many signatures", func(t *testing.T) { testCHECKMULTISIGBad(t, isR1, true, 2, []int{0}, []int{0, 1}) })
t.Run("gas limit exceeded", func(t *testing.T) { t.Run("gas limit exceeded", func(t *testing.T) {
v := initCHECKMULTISIGVM(t, isR1, 1, []int{0}, []int{0}) v := initCHECKMULTISIGVM(t, 1, []int{0}, []int{0})
v.GasLimit = fee.ECDSAVerifyPrice - 1 v.GasLimit = fee.ECDSAVerifyPrice - 1
require.Error(t, v.Run()) require.Error(t, v.Run())
}) })
msg := []byte("NEO - An Open Network For Smart Economy") msg := []byte("NEO - An Open Network For Smart Economy")
pubs, sigs, _, err := initCHECKMULTISIG(isR1, msg, 1) pubs, sigs, _, err := initCHECKMULTISIG(msg, 1)
require.NoError(t, err) require.NoError(t, err)
arr := stackitem.NewArray([]stackitem.Item{stackitem.NewArray(nil)}) arr := stackitem.NewArray([]stackitem.Item{stackitem.NewArray(nil)})
t.Run("invalid message type", func(t *testing.T) { t.Run("invalid message type", func(t *testing.T) {
v := initCheckMultisigVMNoArgs(isR1) v := initCheckMultisigVMNoArgs()
v.Estack().PushVal(sigs) v.Estack().PushVal(sigs)
v.Estack().PushVal(pubs) v.Estack().PushVal(pubs)
v.Estack().PushVal(stackitem.NewArray(nil)) v.Estack().PushVal(stackitem.NewArray(nil))
require.Error(t, v.Run()) require.Error(t, v.Run())
}) })
t.Run("invalid public keys", func(t *testing.T) { t.Run("invalid public keys", func(t *testing.T) {
v := initCheckMultisigVMNoArgs(isR1) v := initCheckMultisigVMNoArgs()
v.Estack().PushVal(sigs) v.Estack().PushVal(sigs)
v.Estack().PushVal(arr) v.Estack().PushVal(arr)
v.Estack().PushVal(msg) v.Estack().PushVal(msg)
require.Error(t, v.Run()) require.Error(t, v.Run())
}) })
t.Run("invalid signatures", func(t *testing.T) { t.Run("invalid signatures", func(t *testing.T) {
v := initCheckMultisigVMNoArgs(isR1) v := initCheckMultisigVMNoArgs()
v.Estack().PushVal(arr) v.Estack().PushVal(arr)
v.Estack().PushVal(pubs) v.Estack().PushVal(pubs)
v.Estack().PushVal(msg) v.Estack().PushVal(msg)

View file

@ -7,13 +7,11 @@ import (
var ( var (
ecdsaSecp256r1CheckMultisigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1)) ecdsaSecp256r1CheckMultisigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1))
ecdsaSecp256k1CheckMultisigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1))
neoCryptoCheckSigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckSig)) neoCryptoCheckSigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckSig))
) )
var cryptoInterops = []interop.Function{ var cryptoInterops = []interop.Function{
{ID: ecdsaSecp256r1CheckMultisigID, Func: ECDSASecp256r1CheckMultisig}, {ID: ecdsaSecp256r1CheckMultisigID, Func: ECDSASecp256r1CheckMultisig},
{ID: ecdsaSecp256k1CheckMultisigID, Func: ECDSASecp256k1CheckMultisig},
{ID: neoCryptoCheckSigID, Func: ECDSASecp256r1CheckSig}, {ID: neoCryptoCheckSigID, Func: ECDSASecp256r1CheckSig},
} }

View file

@ -38,7 +38,6 @@ const (
SystemStoragePut = "System.Storage.Put" SystemStoragePut = "System.Storage.Put"
SystemStorageAsReadOnly = "System.Storage.AsReadOnly" SystemStorageAsReadOnly = "System.Storage.AsReadOnly"
NeoCryptoCheckMultisigWithECDsaSecp256r1 = "Neo.Crypto.CheckMultisigWithECDsaSecp256r1" NeoCryptoCheckMultisigWithECDsaSecp256r1 = "Neo.Crypto.CheckMultisigWithECDsaSecp256r1"
NeoCryptoCheckMultisigWithECDsaSecp256k1 = "Neo.Crypto.CheckMultisigWithECDsaSecp256k1"
NeoCryptoCheckSig = "Neo.Crypto.CheckSig" NeoCryptoCheckSig = "Neo.Crypto.CheckSig"
) )
@ -79,6 +78,5 @@ var names = []string{
SystemStoragePut, SystemStoragePut,
SystemStorageAsReadOnly, SystemStorageAsReadOnly,
NeoCryptoCheckMultisigWithECDsaSecp256r1, NeoCryptoCheckMultisigWithECDsaSecp256r1,
NeoCryptoCheckMultisigWithECDsaSecp256k1,
NeoCryptoCheckSig, NeoCryptoCheckSig,
} }

View file

@ -76,7 +76,6 @@ var systemInterops = []interop.Function{
var neoInterops = []interop.Function{ var neoInterops = []interop.Function{
{Name: interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1, Func: crypto.ECDSASecp256r1CheckMultisig, Price: 0, ParamCount: 3}, {Name: interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1, Func: crypto.ECDSASecp256r1CheckMultisig, Price: 0, ParamCount: 3},
{Name: interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1, Func: crypto.ECDSASecp256k1CheckMultisig, Price: 0, ParamCount: 3},
{Name: interopnames.NeoCryptoCheckSig, Func: crypto.ECDSASecp256r1CheckSig, Price: fee.ECDSAVerifyPrice, ParamCount: 2}, {Name: interopnames.NeoCryptoCheckSig, Func: crypto.ECDSASecp256r1CheckSig, Price: fee.ECDSAVerifyPrice, ParamCount: 2},
} }

View file

@ -14,12 +14,6 @@ func ECDSASecp256r1CheckMultisig(msg []byte, pubs []interop.PublicKey, sigs []in
return neogointernal.Syscall3("Neo.Crypto.CheckMultisigWithECDsaSecp256r1", msg, pubs, sigs).(bool) return neogointernal.Syscall3("Neo.Crypto.CheckMultisigWithECDsaSecp256r1", msg, pubs, sigs).(bool)
} }
// ECDSASecp256k1CheckMultisig checks multiple ECDSA signatures at once. It uses
// `Neo.Crypto.CheckMultisigWithECDsaSecp256k1` syscall.
func ECDSASecp256k1CheckMultisig(msg []byte, pubs []interop.PublicKey, sigs []interop.Signature) bool {
return neogointernal.Syscall3("Neo.Crypto.CheckMultisigWithECDsaSecp256k1", msg, pubs, sigs).(bool)
}
// CheckSig checks that sig is correct script-container's signature for a given pub // CheckSig checks that sig is correct script-container's signature for a given pub
// (serialized public key). It uses `Neo.Crypto.CheckSig` syscall. // (serialized public key). It uses `Neo.Crypto.CheckSig` syscall.
func CheckSig(pub interop.PublicKey, sig interop.Signature) bool { func CheckSig(pub interop.PublicKey, sig interop.Signature) bool {