Skip to content

Commit ac6e7c3

Browse files
authored
Native: extend CryptoLib's verifyWithECDsa with compatible NamedCurveHash argument (#1035)
* Native: mark NamedCurve enum as deprecated It will be replaced by NamedCurveHash in the next commit. A part of neo-project/neo#3209. Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru> * Native: replace NamedCurve enum with NamedCurveHash enum Mark VerifyWithECDsa method as obsolete. Ref. native CryptoLib update from neo-project/neo#3209. Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru> * Native: update NamedCurveHash values for Keccak256 hasher Use 122 and 123 respectively for secp256k1Keccak256 and secp256r1Keccak256. Port the neo-project/neo@e7d9122. Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru> * neo: fetch 3.7.1 version of the neo core Released commit 1d957922a1aec90d0ec852402dc6eca496841ed4. Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru> --------- Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
1 parent 160e8b7 commit ac6e7c3

8 files changed

Lines changed: 101 additions & 9 deletions

File tree

src/Neo.SmartContract.Framework/Native/CryptoLib.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#pragma warning disable CS0626
1212

13+
using System;
1314
using Neo.SmartContract.Framework.Attributes;
1415

1516
namespace Neo.SmartContract.Framework.Native
@@ -28,6 +29,9 @@ public static partial class CryptoLib
2829

2930
public static extern ByteString Murmur32(ByteString value, uint seed);
3031

32+
[Obsolete("VerifyWithECDsa has changed its signature. Please, use a compatible version of VerifyWithECDsa with NamedCurveHash curveHash argument instead.")]
3133
public static extern bool VerifyWithECDsa(ByteString message, ECPoint pubkey, ByteString signature, NamedCurve curve);
34+
35+
public static extern bool VerifyWithECDsa(ByteString message, ECPoint pubkey, ByteString signature, NamedCurveHash curveHash);
3236
}
3337
}

src/Neo.SmartContract.Framework/Native/NamedCurve.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,24 @@
88
// Redistribution and use in source and binary forms with or without
99
// modifications are permitted.
1010

11+
using System;
12+
1113
namespace Neo.SmartContract.Framework.Native
1214
{
1315
/// <summary>
14-
/// RFC 4492
16+
/// Represents the named curve (RFC 4492) used in ECDSA. This enum is obsolete
17+
/// and will be removed in future versions. Please, use an extended compatible
18+
/// <see cref="NamedCurveHash"/> instead.
1519
/// </summary>
1620
/// <remarks>
1721
/// https://tools.ietf.org/html/rfc4492#section-5.1.1
1822
/// </remarks>
23+
[Obsolete("NamedCurve enum is obsolete and will be removed in future versions. Please, use an extended compatible NamedCurveHash instead.")]
1924
public enum NamedCurve : byte
2025
{
26+
[Obsolete("secp256k1 value is obsolete and will be removed in future versions. Please, use NamedCurveHash.secp256k1SHA256 for compatible behaviour.")]
2127
secp256k1 = 22,
28+
[Obsolete("secp256r1 value is obsolete and will be removed in future versions. Please, use NamedCurveHash.secp256r1SHA256 for compatible behaviour.")]
2229
secp256r1 = 23
2330
}
2431
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (C) 2015-2024 The Neo Project.
2+
//
3+
// The Neo.SmartContract.Framework is free software distributed under the MIT
4+
// software license, see the accompanying file LICENSE in the main directory
5+
// of the project or http://www.opensource.org/licenses/mit-license.php
6+
// for more details.
7+
//
8+
// Redistribution and use in source and binary forms with or without
9+
// modifications are permitted.
10+
11+
using System;
12+
13+
namespace Neo.SmartContract.Framework.Native
14+
{
15+
/// <summary>
16+
/// Represents a pair of the named curve used in ECDSA and a hash algorithm used to hash message.
17+
/// This is a compatible extension of an obsolete <see cref="NamedCurve"/> enum.
18+
/// </summary>
19+
public enum NamedCurveHash : byte
20+
{
21+
/// <summary>
22+
/// The secp256k1 curve and SHA256 hash algorithm.
23+
/// </summary>
24+
secp256k1SHA256 = 22,
25+
26+
/// <summary>
27+
/// The secp256r1 curve, which known as prime256v1 or nistP-256, and SHA256 hash algorithm.
28+
/// </summary>
29+
secp256r1SHA256 = 23,
30+
31+
/// <summary>
32+
/// The secp256k1 curve and Keccak256 hash algorithm.
33+
/// </summary>
34+
secp256k1Keccak256 = 122,
35+
36+
/// <summary>
37+
/// The secp256r1 curve, which known as prime256v1 or nistP-256, and Keccak256 hash algorithm.
38+
/// </summary>
39+
secp256r1Keccak256 = 123
40+
}
41+
}

src/Neo.SmartContract.Testing/Native/CryptoLib.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public abstract class CryptoLib : SmartContract
7878
/// Safe method
7979
/// </summary>
8080
[DisplayName("verifyWithECDsa")]
81-
public abstract bool VerifyWithECDsa(byte[] message, byte[] pubkey, byte[] signature, NamedCurve curve);
81+
public abstract bool VerifyWithECDsa(byte[] message, byte[] pubkey, byte[] signature, NamedCurveHash curveHash);
8282

8383
#endregion
8484

tests/Neo.SmartContract.Framework.TestContracts/Contract_Crypto.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,22 @@ public static byte[] Murmur32(byte[] value, uint seed)
2424

2525
public static bool Secp256r1VerifySignatureWithMessage(byte[] message, ECPoint pubkey, byte[] signature)
2626
{
27-
return CryptoLib.VerifyWithECDsa((ByteString)message, pubkey, (ByteString)signature, NamedCurve.secp256r1);
27+
return CryptoLib.VerifyWithECDsa((ByteString)message, pubkey, (ByteString)signature, NamedCurveHash.secp256r1SHA256);
28+
}
29+
30+
public static bool Secp256r1VerifyKeccakSignatureWithMessage(byte[] message, ECPoint pubkey, byte[] signature)
31+
{
32+
return CryptoLib.VerifyWithECDsa((ByteString)message, pubkey, (ByteString)signature, NamedCurveHash.secp256r1Keccak256);
2833
}
2934

3035
public static bool Secp256k1VerifySignatureWithMessage(byte[] message, ECPoint pubkey, byte[] signature)
3136
{
32-
return CryptoLib.VerifyWithECDsa((ByteString)message, pubkey, (ByteString)signature, NamedCurve.secp256k1);
37+
return CryptoLib.VerifyWithECDsa((ByteString)message, pubkey, (ByteString)signature, NamedCurveHash.secp256k1SHA256);
38+
}
39+
40+
public static bool Secp256k1VerifyKeccakSignatureWithMessage(byte[] message, ECPoint pubkey, byte[] signature)
41+
{
42+
return CryptoLib.VerifyWithECDsa((ByteString)message, pubkey, (ByteString)signature, NamedCurveHash.secp256k1Keccak256);
3343
}
3444

3545
public static byte[] Bls12381Serialize(object data)

tests/Neo.SmartContract.Framework.UnitTests/Services/CryptoTest.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public void Test_RIPEMD160()
5252
[TestMethod]
5353
public void Test_VerifySignatureWithMessage()
5454
{
55-
// secp256r1
55+
// secp256r1 with SHA256 hash
5656

5757
var key = GenerateKey(32);
5858
var data = Engine.Transaction.GetSignData(ProtocolSettings.Default.Network);
@@ -63,7 +63,16 @@ public void Test_VerifySignatureWithMessage()
6363
Assert.IsFalse(Contract.Secp256r1VerifySignatureWithMessage(System.Array.Empty<byte>(), key.PublicKey, signature));
6464
Assert.IsTrue(Contract.Secp256r1VerifySignatureWithMessage(data, key.PublicKey, signature));
6565

66-
// secp256k1
66+
// secp256r1 with Keccak hash
67+
68+
var signatureKeccak = Crypto.Sign(data, key.PrivateKey, hasher: Hasher.Keccak256);
69+
70+
// Check
71+
72+
Assert.IsFalse(Contract.Secp256r1VerifyKeccakSignatureWithMessage(System.Array.Empty<byte>(), key.PublicKey, signatureKeccak));
73+
Assert.IsTrue(Contract.Secp256r1VerifyKeccakSignatureWithMessage(data, key.PublicKey, signatureKeccak));
74+
75+
// secp256k1 with SHA256 hash
6776

6877
var pubkey = Cryptography.ECC.ECCurve.Secp256k1.G * key.PrivateKey;
6978
var pubKeyData = pubkey.EncodePoint(false).Skip(1).ToArray();
@@ -83,6 +92,15 @@ public void Test_VerifySignatureWithMessage()
8392

8493
Assert.IsFalse(Contract.Secp256k1VerifySignatureWithMessage(System.Array.Empty<byte>(), pubkey, signature));
8594
Assert.IsTrue(Contract.Secp256k1VerifySignatureWithMessage(data, pubkey, signature));
95+
96+
// secp256k1 with Keccak hash
97+
98+
signature = Crypto.Sign(data, key.PrivateKey, ecCurve: Cryptography.ECC.ECCurve.Secp256k1, hasher: Hasher.Keccak256);
99+
100+
// Check
101+
102+
Assert.IsFalse(Contract.Secp256k1VerifyKeccakSignatureWithMessage(System.Array.Empty<byte>(), pubkey, signature));
103+
Assert.IsTrue(Contract.Secp256k1VerifyKeccakSignatureWithMessage(data, pubkey, signature));
86104
}
87105

88106
[TestMethod]

tests/Neo.SmartContract.Framework.UnitTests/TestingArtifacts/Contract_Crypto.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ public abstract class Contract_Crypto : Neo.SmartContract.Testing.SmartContract
1010
{
1111
#region Compiled data
1212

13-
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"":{}}");
13+
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"":{}}");
1414

15-
public static readonly Neo.SmartContract.NefFile Nef = Neo.IO.Helper.AsSerializable<Neo.SmartContract.NefFile>(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAob9XWrEYlohBNhCjWhKIbN4LZscgZzaGEyNTYBAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIJcmlwZW1kMTYwAQABDxv1dasRiWiEE2EKNaEohs3gtmxyCG11cm11cjMyAgABDxv1dasRiWiEE2EKNaEohs3gtmxyD3ZlcmlmeVdpdGhFQ0RzYQQAAQ8b9XWrEYlohBNhCjWhKIbN4LZschFibHMxMjM4MVNlcmlhbGl6ZQEAAQ8b9XWrEYlohBNhCjWhKIbN4LZschNibHMxMjM4MURlc2VyaWFsaXplAQABDxv1dasRiWiEE2EKNaEohs3gtmxyDWJsczEyMzgxRXF1YWwCAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHILYmxzMTIzODFBZGQCAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHILYmxzMTIzODFNdWwDAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIPYmxzMTIzODFQYWlyaW5nAgABDwAAkFcAAXjbKDcAANswIgJAVwABeNsoNwEA2zAiAkBXAAJ5eNsoNwIA2zAiAkBXAAMAF3rbKHl42yg3AwAiAkBXAAMAFnrbKHl42yg3AwAiAkBXAAF4NwQAIgJAVwABeDcFACICQFcAAnl4NwYAIgJAVwACeXg3BwAiAkBXAAN6eXg3CAAiAkBXAAJ5eDcJACICQBCN0V0="));
15+
public static readonly Neo.SmartContract.NefFile Nef = Neo.IO.Helper.AsSerializable<Neo.SmartContract.NefFile>(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAob9XWrEYlohBNhCjWhKIbN4LZscgZzaGEyNTYBAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIJcmlwZW1kMTYwAQABDxv1dasRiWiEE2EKNaEohs3gtmxyCG11cm11cjMyAgABDxv1dasRiWiEE2EKNaEohs3gtmxyD3ZlcmlmeVdpdGhFQ0RzYQQAAQ8b9XWrEYlohBNhCjWhKIbN4LZschFibHMxMjM4MVNlcmlhbGl6ZQEAAQ8b9XWrEYlohBNhCjWhKIbN4LZschNibHMxMjM4MURlc2VyaWFsaXplAQABDxv1dasRiWiEE2EKNaEohs3gtmxyDWJsczEyMzgxRXF1YWwCAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHILYmxzMTIzODFBZGQCAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHILYmxzMTIzODFNdWwDAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIPYmxzMTIzODFQYWlyaW5nAgABDwAAtFcAAXjbKDcAANswIgJAVwABeNsoNwEA2zAiAkBXAAJ5eNsoNwIA2zAiAkBXAAMAF3rbKHl42yg3AwAiAkBXAAMAe3rbKHl42yg3AwAiAkBXAAMAFnrbKHl42yg3AwAiAkBXAAMAenrbKHl42yg3AwAiAkBXAAF4NwQAIgJAVwABeDcFACICQFcAAnl4NwYAIgJAVwACeXg3BwAiAkBXAAN6eXg3CAAiAkBXAAJ5eDcJACICQD/5x9k="));
1616

1717
#endregion
1818

@@ -65,12 +65,24 @@ public abstract class Contract_Crypto : Neo.SmartContract.Testing.SmartContract
6565
/// </summary>
6666
public abstract byte[]? RIPEMD160(byte[]? value);
6767

68+
/// <summary>
69+
/// Unsafe method
70+
/// </summary>
71+
[DisplayName("secp256k1VerifyKeccakSignatureWithMessage")]
72+
public abstract bool? Secp256k1VerifyKeccakSignatureWithMessage(byte[]? message, ECPoint? pubkey, byte[]? signature);
73+
6874
/// <summary>
6975
/// Unsafe method
7076
/// </summary>
7177
[DisplayName("secp256k1VerifySignatureWithMessage")]
7278
public abstract bool? Secp256k1VerifySignatureWithMessage(byte[]? message, ECPoint? pubkey, byte[]? signature);
7379

80+
/// <summary>
81+
/// Unsafe method
82+
/// </summary>
83+
[DisplayName("secp256r1VerifyKeccakSignatureWithMessage")]
84+
public abstract bool? Secp256r1VerifyKeccakSignatureWithMessage(byte[]? message, ECPoint? pubkey, byte[]? signature);
85+
7486
/// <summary>
7587
/// Unsafe method
7688
/// </summary>

0 commit comments

Comments
 (0)