From 77a3554ba46013c9fef0291cd8590a6116246269 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 6 May 2024 11:29:41 +0300 Subject: [PATCH] Native: replace NamedCurve enum with NamedCurveHash enum Mark VerifyWithECDsa method as obsolete. Ref. native CryptoLib update from https://github.com/neo-project/neo/pull/3209. Signed-off-by: Anna Shaleva --- .../Native/CryptoLib.cs | 4 ++ .../Native/NamedCurveHash.cs | 44 +++++++++++++++++++ .../Native/CryptoLib.cs | 2 +- .../Contract_Crypto.cs | 14 +++++- .../Services/CryptoTest.cs | 22 +++++++++- .../TestingArtifacts/Contract_Crypto.cs | 16 ++++++- 6 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 src/Neo.SmartContract.Framework/Native/NamedCurveHash.cs diff --git a/src/Neo.SmartContract.Framework/Native/CryptoLib.cs b/src/Neo.SmartContract.Framework/Native/CryptoLib.cs index 43dc85d16..149830c00 100644 --- a/src/Neo.SmartContract.Framework/Native/CryptoLib.cs +++ b/src/Neo.SmartContract.Framework/Native/CryptoLib.cs @@ -10,6 +10,7 @@ #pragma warning disable CS0626 +using System; using Neo.SmartContract.Framework.Attributes; namespace Neo.SmartContract.Framework.Native @@ -28,6 +29,9 @@ public static partial class CryptoLib public static extern ByteString Murmur32(ByteString value, uint seed); + [Obsolete("VerifyWithECDsa has changed its signature. Please, use a compatible version of VerifyWithECDsa with NamedCurveHash curveHash argument instead.")] public static extern bool VerifyWithECDsa(ByteString message, ECPoint pubkey, ByteString signature, NamedCurve curve); + + public static extern bool VerifyWithECDsa(ByteString message, ECPoint pubkey, ByteString signature, NamedCurveHash curveHash); } } diff --git a/src/Neo.SmartContract.Framework/Native/NamedCurveHash.cs b/src/Neo.SmartContract.Framework/Native/NamedCurveHash.cs new file mode 100644 index 000000000..575c3bfbd --- /dev/null +++ b/src/Neo.SmartContract.Framework/Native/NamedCurveHash.cs @@ -0,0 +1,44 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// The Neo.SmartContract.Framework is free software distributed under the MIT +// software license, see the accompanying file LICENSE in the main directory +// of the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; + +namespace Neo.SmartContract.Framework.Native +{ + /// + /// Represents a pair of the named curve used in ECDSA and a hash algorithm used to hash message. + /// This is a compatible extension of an obsolete enum. + /// + /// + /// https://tools.ietf.org/html/rfc4492#section-5.1.1 + /// + public enum NamedCurveHash : byte + { + /// + /// The secp256k1 curve and SHA256 hash algorithm. + /// + secp256k1SHA256 = 22, + + /// + /// The secp256r1 curve, which known as prime256v1 or nistP-256, and SHA256 hash algorithm. + /// + secp256r1SHA256 = 23, + + /// + /// The secp256k1 curve and Keccak256 hash algorithm. + /// + secp256k1Keccak256 = 24, + + /// + /// The secp256r1 curve, which known as prime256v1 or nistP-256, and Keccak256 hash algorithm. + /// + secp256r1Keccak256 = 25 + } +} diff --git a/src/Neo.SmartContract.Testing/Native/CryptoLib.cs b/src/Neo.SmartContract.Testing/Native/CryptoLib.cs index 6f71947b5..7cd45a003 100644 --- a/src/Neo.SmartContract.Testing/Native/CryptoLib.cs +++ b/src/Neo.SmartContract.Testing/Native/CryptoLib.cs @@ -78,7 +78,7 @@ public abstract class CryptoLib : SmartContract /// Safe method /// [DisplayName("verifyWithECDsa")] - public abstract bool VerifyWithECDsa(byte[] message, byte[] pubkey, byte[] signature, NamedCurve curve); + public abstract bool VerifyWithECDsa(byte[] message, byte[] pubkey, byte[] signature, NamedCurveHash curveHash); #endregion diff --git a/tests/Neo.SmartContract.Framework.TestContracts/Contract_Crypto.cs b/tests/Neo.SmartContract.Framework.TestContracts/Contract_Crypto.cs index 4106125d8..5e505f9aa 100644 --- a/tests/Neo.SmartContract.Framework.TestContracts/Contract_Crypto.cs +++ b/tests/Neo.SmartContract.Framework.TestContracts/Contract_Crypto.cs @@ -24,12 +24,22 @@ public static byte[] Murmur32(byte[] value, uint seed) public static bool Secp256r1VerifySignatureWithMessage(byte[] message, ECPoint pubkey, byte[] signature) { - return CryptoLib.VerifyWithECDsa((ByteString)message, pubkey, (ByteString)signature, NamedCurve.secp256r1); + return CryptoLib.VerifyWithECDsa((ByteString)message, pubkey, (ByteString)signature, NamedCurveHash.secp256r1SHA256); + } + + public static bool Secp256r1VerifyKeccakSignatureWithMessage(byte[] message, ECPoint pubkey, byte[] signature) + { + return CryptoLib.VerifyWithECDsa((ByteString)message, pubkey, (ByteString)signature, NamedCurveHash.secp256r1Keccak256); } public static bool Secp256k1VerifySignatureWithMessage(byte[] message, ECPoint pubkey, byte[] signature) { - return CryptoLib.VerifyWithECDsa((ByteString)message, pubkey, (ByteString)signature, NamedCurve.secp256k1); + return CryptoLib.VerifyWithECDsa((ByteString)message, pubkey, (ByteString)signature, NamedCurveHash.secp256k1SHA256); + } + + public static bool Secp256k1VerifyKeccakSignatureWithMessage(byte[] message, ECPoint pubkey, byte[] signature) + { + return CryptoLib.VerifyWithECDsa((ByteString)message, pubkey, (ByteString)signature, NamedCurveHash.secp256k1Keccak256); } public static byte[] Bls12381Serialize(object data) diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/CryptoTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/CryptoTest.cs index 494038d32..47e0c9564 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Services/CryptoTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/CryptoTest.cs @@ -52,7 +52,7 @@ public void Test_RIPEMD160() [TestMethod] public void Test_VerifySignatureWithMessage() { - // secp256r1 + // secp256r1 with SHA256 hash var key = GenerateKey(32); var data = Engine.Transaction.GetSignData(ProtocolSettings.Default.Network); @@ -63,7 +63,16 @@ public void Test_VerifySignatureWithMessage() Assert.IsFalse(Contract.Secp256r1VerifySignatureWithMessage(System.Array.Empty(), key.PublicKey, signature)); Assert.IsTrue(Contract.Secp256r1VerifySignatureWithMessage(data, key.PublicKey, signature)); - // secp256k1 + // secp256r1 with Keccak hash + + var signatureKeccak = Crypto.Sign(data, key.PrivateKey, hasher: Hasher.Keccak256); + + // Check + + Assert.IsFalse(Contract.Secp256r1VerifyKeccakSignatureWithMessage(System.Array.Empty(), key.PublicKey, signatureKeccak)); + Assert.IsTrue(Contract.Secp256r1VerifyKeccakSignatureWithMessage(data, key.PublicKey, signatureKeccak)); + + // secp256k1 with SHA256 hash var pubkey = Cryptography.ECC.ECCurve.Secp256k1.G * key.PrivateKey; var pubKeyData = pubkey.EncodePoint(false).Skip(1).ToArray(); @@ -83,6 +92,15 @@ public void Test_VerifySignatureWithMessage() Assert.IsFalse(Contract.Secp256k1VerifySignatureWithMessage(System.Array.Empty(), pubkey, signature)); Assert.IsTrue(Contract.Secp256k1VerifySignatureWithMessage(data, pubkey, signature)); + + // secp256k1 with Keccak hash + + signature = Crypto.Sign(data, key.PrivateKey, ecCurve: Cryptography.ECC.ECCurve.Secp256k1, hasher: Hasher.Keccak256); + + // Check + + Assert.IsFalse(Contract.Secp256k1VerifyKeccakSignatureWithMessage(System.Array.Empty(), pubkey, signature)); + Assert.IsTrue(Contract.Secp256k1VerifyKeccakSignatureWithMessage(data, pubkey, signature)); } [TestMethod] diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestingArtifacts/Contract_Crypto.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestingArtifacts/Contract_Crypto.cs index 7373300eb..fb82975d7 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/TestingArtifacts/Contract_Crypto.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestingArtifacts/Contract_Crypto.cs @@ -10,9 +10,9 @@ public abstract class Contract_Crypto : Neo.SmartContract.Testing.SmartContract { #region Compiled data - public static readonly Neo.SmartContract.Manifest.ContractManifest Manifest = Neo.SmartContract.Manifest.ContractManifest.Parse(@"{""name"":""Contract_Crypto"",""groups"":[],""features"":{},""supportedstandards"":[],""abi"":{""methods"":[{""name"":""SHA256"",""parameters"":[{""name"":""value"",""type"":""ByteArray""}],""returntype"":""ByteArray"",""offset"":0,""safe"":false},{""name"":""RIPEMD160"",""parameters"":[{""name"":""value"",""type"":""ByteArray""}],""returntype"":""ByteArray"",""offset"":14,""safe"":false},{""name"":""murmur32"",""parameters"":[{""name"":""value"",""type"":""ByteArray""},{""name"":""seed"",""type"":""Integer""}],""returntype"":""ByteArray"",""offset"":28,""safe"":false},{""name"":""secp256r1VerifySignatureWithMessage"",""parameters"":[{""name"":""message"",""type"":""ByteArray""},{""name"":""pubkey"",""type"":""PublicKey""},{""name"":""signature"",""type"":""ByteArray""}],""returntype"":""Boolean"",""offset"":43,""safe"":false},{""name"":""secp256k1VerifySignatureWithMessage"",""parameters"":[{""name"":""message"",""type"":""ByteArray""},{""name"":""pubkey"",""type"":""PublicKey""},{""name"":""signature"",""type"":""ByteArray""}],""returntype"":""Boolean"",""offset"":61,""safe"":false},{""name"":""bls12381Serialize"",""parameters"":[{""name"":""data"",""type"":""Any""}],""returntype"":""ByteArray"",""offset"":79,""safe"":false},{""name"":""bls12381Deserialize"",""parameters"":[{""name"":""data"",""type"":""ByteArray""}],""returntype"":""Any"",""offset"":89,""safe"":false},{""name"":""bls12381Equal"",""parameters"":[{""name"":""x"",""type"":""Any""},{""name"":""y"",""type"":""Any""}],""returntype"":""Any"",""offset"":99,""safe"":false},{""name"":""bls12381Add"",""parameters"":[{""name"":""x"",""type"":""Any""},{""name"":""y"",""type"":""Any""}],""returntype"":""Any"",""offset"":110,""safe"":false},{""name"":""bls12381Mul"",""parameters"":[{""name"":""x"",""type"":""Any""},{""name"":""mul"",""type"":""ByteArray""},{""name"":""neg"",""type"":""Boolean""}],""returntype"":""Any"",""offset"":121,""safe"":false},{""name"":""bls12381Pairing"",""parameters"":[{""name"":""g1"",""type"":""Any""},{""name"":""g2"",""type"":""Any""}],""returntype"":""Any"",""offset"":133,""safe"":false}],""events"":[]},""permissions"":[{""contract"":""0x726cb6e0cd8628a1350a611384688911ab75f51b"",""methods"":[""bls12381Add"",""bls12381Deserialize"",""bls12381Equal"",""bls12381Mul"",""bls12381Pairing"",""bls12381Serialize"",""murmur32"",""ripemd160"",""sha256"",""verifyWithECDsa""]}],""trusts"":[],""extra"":{}}"); + public static readonly Neo.SmartContract.Manifest.ContractManifest Manifest = Neo.SmartContract.Manifest.ContractManifest.Parse(@"{""name"":""Contract_Crypto"",""groups"":[],""features"":{},""supportedstandards"":[],""abi"":{""methods"":[{""name"":""SHA256"",""parameters"":[{""name"":""value"",""type"":""ByteArray""}],""returntype"":""ByteArray"",""offset"":0,""safe"":false},{""name"":""RIPEMD160"",""parameters"":[{""name"":""value"",""type"":""ByteArray""}],""returntype"":""ByteArray"",""offset"":14,""safe"":false},{""name"":""murmur32"",""parameters"":[{""name"":""value"",""type"":""ByteArray""},{""name"":""seed"",""type"":""Integer""}],""returntype"":""ByteArray"",""offset"":28,""safe"":false},{""name"":""secp256r1VerifySignatureWithMessage"",""parameters"":[{""name"":""message"",""type"":""ByteArray""},{""name"":""pubkey"",""type"":""PublicKey""},{""name"":""signature"",""type"":""ByteArray""}],""returntype"":""Boolean"",""offset"":43,""safe"":false},{""name"":""secp256r1VerifyKeccakSignatureWithMessage"",""parameters"":[{""name"":""message"",""type"":""ByteArray""},{""name"":""pubkey"",""type"":""PublicKey""},{""name"":""signature"",""type"":""ByteArray""}],""returntype"":""Boolean"",""offset"":61,""safe"":false},{""name"":""secp256k1VerifySignatureWithMessage"",""parameters"":[{""name"":""message"",""type"":""ByteArray""},{""name"":""pubkey"",""type"":""PublicKey""},{""name"":""signature"",""type"":""ByteArray""}],""returntype"":""Boolean"",""offset"":79,""safe"":false},{""name"":""secp256k1VerifyKeccakSignatureWithMessage"",""parameters"":[{""name"":""message"",""type"":""ByteArray""},{""name"":""pubkey"",""type"":""PublicKey""},{""name"":""signature"",""type"":""ByteArray""}],""returntype"":""Boolean"",""offset"":97,""safe"":false},{""name"":""bls12381Serialize"",""parameters"":[{""name"":""data"",""type"":""Any""}],""returntype"":""ByteArray"",""offset"":115,""safe"":false},{""name"":""bls12381Deserialize"",""parameters"":[{""name"":""data"",""type"":""ByteArray""}],""returntype"":""Any"",""offset"":125,""safe"":false},{""name"":""bls12381Equal"",""parameters"":[{""name"":""x"",""type"":""Any""},{""name"":""y"",""type"":""Any""}],""returntype"":""Any"",""offset"":135,""safe"":false},{""name"":""bls12381Add"",""parameters"":[{""name"":""x"",""type"":""Any""},{""name"":""y"",""type"":""Any""}],""returntype"":""Any"",""offset"":146,""safe"":false},{""name"":""bls12381Mul"",""parameters"":[{""name"":""x"",""type"":""Any""},{""name"":""mul"",""type"":""ByteArray""},{""name"":""neg"",""type"":""Boolean""}],""returntype"":""Any"",""offset"":157,""safe"":false},{""name"":""bls12381Pairing"",""parameters"":[{""name"":""g1"",""type"":""Any""},{""name"":""g2"",""type"":""Any""}],""returntype"":""Any"",""offset"":169,""safe"":false}],""events"":[]},""permissions"":[{""contract"":""0x726cb6e0cd8628a1350a611384688911ab75f51b"",""methods"":[""bls12381Add"",""bls12381Deserialize"",""bls12381Equal"",""bls12381Mul"",""bls12381Pairing"",""bls12381Serialize"",""murmur32"",""ripemd160"",""sha256"",""verifyWithECDsa""]}],""trusts"":[],""extra"":{}}"); - public static readonly Neo.SmartContract.NefFile Nef = Neo.IO.Helper.AsSerializable(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAob9XWrEYlohBNhCjWhKIbN4LZscgZzaGEyNTYBAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIJcmlwZW1kMTYwAQABDxv1dasRiWiEE2EKNaEohs3gtmxyCG11cm11cjMyAgABDxv1dasRiWiEE2EKNaEohs3gtmxyD3ZlcmlmeVdpdGhFQ0RzYQQAAQ8b9XWrEYlohBNhCjWhKIbN4LZschFibHMxMjM4MVNlcmlhbGl6ZQEAAQ8b9XWrEYlohBNhCjWhKIbN4LZschNibHMxMjM4MURlc2VyaWFsaXplAQABDxv1dasRiWiEE2EKNaEohs3gtmxyDWJsczEyMzgxRXF1YWwCAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHILYmxzMTIzODFBZGQCAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHILYmxzMTIzODFNdWwDAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIPYmxzMTIzODFQYWlyaW5nAgABDwAAkFcAAXjbKDcAANswIgJAVwABeNsoNwEA2zAiAkBXAAJ5eNsoNwIA2zAiAkBXAAMAF3rbKHl42yg3AwAiAkBXAAMAFnrbKHl42yg3AwAiAkBXAAF4NwQAIgJAVwABeDcFACICQFcAAnl4NwYAIgJAVwACeXg3BwAiAkBXAAN6eXg3CAAiAkBXAAJ5eDcJACICQBCN0V0=")); + public static readonly Neo.SmartContract.NefFile Nef = Neo.IO.Helper.AsSerializable(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAob9XWrEYlohBNhCjWhKIbN4LZscgZzaGEyNTYBAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIJcmlwZW1kMTYwAQABDxv1dasRiWiEE2EKNaEohs3gtmxyCG11cm11cjMyAgABDxv1dasRiWiEE2EKNaEohs3gtmxyD3ZlcmlmeVdpdGhFQ0RzYQQAAQ8b9XWrEYlohBNhCjWhKIbN4LZschFibHMxMjM4MVNlcmlhbGl6ZQEAAQ8b9XWrEYlohBNhCjWhKIbN4LZschNibHMxMjM4MURlc2VyaWFsaXplAQABDxv1dasRiWiEE2EKNaEohs3gtmxyDWJsczEyMzgxRXF1YWwCAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHILYmxzMTIzODFBZGQCAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHILYmxzMTIzODFNdWwDAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIPYmxzMTIzODFQYWlyaW5nAgABDwAAtFcAAXjbKDcAANswIgJAVwABeNsoNwEA2zAiAkBXAAJ5eNsoNwIA2zAiAkBXAAMAF3rbKHl42yg3AwAiAkBXAAMAe3rbKHl42yg3AwAiAkBXAAMAFnrbKHl42yg3AwAiAkBXAAMAenrbKHl42yg3AwAiAkBXAAF4NwQAIgJAVwABeDcFACICQFcAAnl4NwYAIgJAVwACeXg3BwAiAkBXAAN6eXg3CAAiAkBXAAJ5eDcJACICQD/5x9k=")); #endregion @@ -65,12 +65,24 @@ public abstract class Contract_Crypto : Neo.SmartContract.Testing.SmartContract /// public abstract byte[]? RIPEMD160(byte[]? value); + /// + /// Unsafe method + /// + [DisplayName("secp256k1VerifyKeccakSignatureWithMessage")] + public abstract bool? Secp256k1VerifyKeccakSignatureWithMessage(byte[]? message, ECPoint? pubkey, byte[]? signature); + /// /// Unsafe method /// [DisplayName("secp256k1VerifySignatureWithMessage")] public abstract bool? Secp256k1VerifySignatureWithMessage(byte[]? message, ECPoint? pubkey, byte[]? signature); + /// + /// Unsafe method + /// + [DisplayName("secp256r1VerifyKeccakSignatureWithMessage")] + public abstract bool? Secp256r1VerifyKeccakSignatureWithMessage(byte[]? message, ECPoint? pubkey, byte[]? signature); + /// /// Unsafe method ///