core: add Neo.Crypto.CheckSig interop

This commit is contained in:
Anna Shaleva 2021-03-04 20:56:54 +03:00
parent 14ade42101
commit 4e6c1092b8
7 changed files with 87 additions and 0 deletions

View file

@ -93,6 +93,7 @@ func TestSyscallExecution(t *testing.T) {
"crypto.ECDsaSecp256k1Verify": {interopnames.NeoCryptoVerifyWithECDsaSecp256k1, []string{b, pub, sig}, 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},
}
ic := &interop.Context{}
core.SpawnVM(ic) // set Functions field

View file

@ -99,3 +99,17 @@ func getMessageHash(ic *interop.Context, item stackitem.Item) (util.Uint256, err
}
return hash.Sha256(msg), nil
}
// ECDSASecp256r1CheckSig checks ECDSA signature using Secp256r1 elliptic curve.
func ECDSASecp256r1CheckSig(ic *interop.Context) error {
hashToCheck := ic.Container.GetSignedHash()
keyb := ic.VM.Estack().Pop().Bytes()
signature := ic.VM.Estack().Pop().Bytes()
pkey, err := keys.NewPublicKeyFromBytes(keyb, elliptic.P256())
if err != nil {
return err
}
res := pkey.Verify(signature, hashToCheck.BytesBE())
ic.VM.Estack().PushVal(res)
return nil
}

View file

@ -279,3 +279,64 @@ func testCurveCHECKMULTISIGBad(t *testing.T, isR1 bool) {
require.Error(t, v.Run())
})
}
func TestCheckSig(t *testing.T) {
priv, err := keys.NewPrivateKey()
require.NoError(t, err)
verifyFunc := ECDSASecp256r1CheckSig
d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false)
ic := &interop.Context{DAO: dao.NewCached(d)}
runCase := func(t *testing.T, isErr bool, result interface{}, args ...interface{}) {
ic.SpawnVM()
for i := range args {
ic.VM.Estack().PushVal(args[i])
}
var err error
func() {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic: %v", r)
}
}()
err = verifyFunc(ic)
}()
if isErr {
require.Error(t, err)
return
}
require.NoError(t, err)
require.Equal(t, 1, ic.VM.Estack().Len())
require.Equal(t, result, ic.VM.Estack().Pop().Value().(bool))
}
tx := transaction.New(netmode.UnitTestNet, []byte{0, 1, 2}, 1)
msg := tx.GetSignedPart()
ic.Container = tx
t.Run("success", func(t *testing.T) {
sign := priv.Sign(msg)
runCase(t, false, true, sign, priv.PublicKey().Bytes())
})
t.Run("missing argument", func(t *testing.T) {
runCase(t, true, false)
sign := priv.Sign(msg)
runCase(t, true, false, sign)
})
t.Run("invalid signature", func(t *testing.T) {
sign := priv.Sign(msg)
sign[0] = ^sign[0]
runCase(t, false, false, sign, priv.PublicKey().Bytes())
})
t.Run("invalid public key", func(t *testing.T) {
sign := priv.Sign(msg)
pub := priv.PublicKey().Bytes()
pub[0] = 0xFF // invalid prefix
runCase(t, true, false, sign, pub)
})
}

View file

@ -10,6 +10,7 @@ var (
ecdsaSecp256k1VerifyID = interopnames.ToID([]byte(interopnames.NeoCryptoVerifyWithECDsaSecp256k1))
ecdsaSecp256r1CheckMultisigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1))
ecdsaSecp256k1CheckMultisigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1))
neoCryptoCheckSigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckSig))
)
var cryptoInterops = []interop.Function{
@ -17,6 +18,7 @@ var cryptoInterops = []interop.Function{
{ID: ecdsaSecp256k1VerifyID, Func: ECDSASecp256k1Verify},
{ID: ecdsaSecp256r1CheckMultisigID, Func: ECDSASecp256r1CheckMultisig},
{ID: ecdsaSecp256k1CheckMultisigID, Func: ECDSASecp256k1CheckMultisig},
{ID: neoCryptoCheckSigID, Func: ECDSASecp256r1CheckSig},
}
func init() {

View file

@ -41,6 +41,7 @@ const (
NeoCryptoVerifyWithECDsaSecp256k1 = "Neo.Crypto.VerifyWithECDsaSecp256k1"
NeoCryptoCheckMultisigWithECDsaSecp256r1 = "Neo.Crypto.CheckMultisigWithECDsaSecp256r1"
NeoCryptoCheckMultisigWithECDsaSecp256k1 = "Neo.Crypto.CheckMultisigWithECDsaSecp256k1"
NeoCryptoCheckSig = "Neo.Crypto.CheckSig"
)
var names = []string{
@ -83,4 +84,5 @@ var names = []string{
NeoCryptoVerifyWithECDsaSecp256k1,
NeoCryptoCheckMultisigWithECDsaSecp256r1,
NeoCryptoCheckMultisigWithECDsaSecp256k1,
NeoCryptoCheckSig,
}

View file

@ -81,6 +81,7 @@ var neoInterops = []interop.Function{
Price: fee.ECDSAVerifyPrice, 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},
}
// initIDinInteropsSlice initializes IDs from names in one given

View file

@ -31,3 +31,9 @@ func ECDSASecp256r1CheckMultisig(msg []byte, pubs []interop.PublicKey, sigs []in
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
// (serialized public key). It uses `Neo.Crypto.CheckSig` syscall.
func CheckSig(pub interop.PublicKey, sig interop.Signature) bool {
return neogointernal.Syscall2("Neo.Crypto.CheckSig", pub, sig).(bool)
}