Skip to content

Commit

Permalink
Native: extend CryptoLib's verifyWithECDsa with compatible `NamedCu…
Browse files Browse the repository at this point in the history
…rveHash` 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>
  • Loading branch information
AnnaShaleva committed May 11, 2024
1 parent 160e8b7 commit ac6e7c3
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 9 deletions.
4 changes: 4 additions & 0 deletions src/Neo.SmartContract.Framework/Native/CryptoLib.cs
Expand Up @@ -10,6 +10,7 @@

#pragma warning disable CS0626

using System;
using Neo.SmartContract.Framework.Attributes;

namespace Neo.SmartContract.Framework.Native
Expand All @@ -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);
}
}
9 changes: 8 additions & 1 deletion src/Neo.SmartContract.Framework/Native/NamedCurve.cs
Expand Up @@ -8,17 +8,24 @@
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using System;

namespace Neo.SmartContract.Framework.Native
{
/// <summary>
/// RFC 4492
/// Represents the named curve (RFC 4492) used in ECDSA. This enum is obsolete
/// and will be removed in future versions. Please, use an extended compatible
/// <see cref="NamedCurveHash"/> instead.
/// </summary>
/// <remarks>
/// https://tools.ietf.org/html/rfc4492#section-5.1.1
/// </remarks>
[Obsolete("NamedCurve enum is obsolete and will be removed in future versions. Please, use an extended compatible NamedCurveHash instead.")]
public enum NamedCurve : byte
{
[Obsolete("secp256k1 value is obsolete and will be removed in future versions. Please, use NamedCurveHash.secp256k1SHA256 for compatible behaviour.")]
secp256k1 = 22,
[Obsolete("secp256r1 value is obsolete and will be removed in future versions. Please, use NamedCurveHash.secp256r1SHA256 for compatible behaviour.")]
secp256r1 = 23
}
}
41 changes: 41 additions & 0 deletions src/Neo.SmartContract.Framework/Native/NamedCurveHash.cs
@@ -0,0 +1,41 @@
// 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
{
/// <summary>
/// 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 <see cref="NamedCurve"/> enum.
/// </summary>
public enum NamedCurveHash : byte
{
/// <summary>
/// The secp256k1 curve and SHA256 hash algorithm.
/// </summary>
secp256k1SHA256 = 22,

/// <summary>
/// The secp256r1 curve, which known as prime256v1 or nistP-256, and SHA256 hash algorithm.
/// </summary>
secp256r1SHA256 = 23,

/// <summary>
/// The secp256k1 curve and Keccak256 hash algorithm.
/// </summary>
secp256k1Keccak256 = 122,

/// <summary>
/// The secp256r1 curve, which known as prime256v1 or nistP-256, and Keccak256 hash algorithm.
/// </summary>
secp256r1Keccak256 = 123
}
}
2 changes: 1 addition & 1 deletion src/Neo.SmartContract.Testing/Native/CryptoLib.cs
Expand Up @@ -78,7 +78,7 @@ public abstract class CryptoLib : SmartContract
/// Safe method
/// </summary>
[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

Expand Down
14 changes: 12 additions & 2 deletions tests/Neo.SmartContract.Framework.TestContracts/Contract_Crypto.cs
Expand Up @@ -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)
Expand Down
22 changes: 20 additions & 2 deletions tests/Neo.SmartContract.Framework.UnitTests/Services/CryptoTest.cs
Expand Up @@ -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);
Expand All @@ -63,7 +63,16 @@ public void Test_VerifySignatureWithMessage()
Assert.IsFalse(Contract.Secp256r1VerifySignatureWithMessage(System.Array.Empty<byte>(), 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<byte>(), 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();
Expand All @@ -83,6 +92,15 @@ public void Test_VerifySignatureWithMessage()

Assert.IsFalse(Contract.Secp256k1VerifySignatureWithMessage(System.Array.Empty<byte>(), 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<byte>(), pubkey, signature));
Assert.IsTrue(Contract.Secp256k1VerifyKeccakSignatureWithMessage(data, pubkey, signature));
}

[TestMethod]
Expand Down
Expand Up @@ -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<Neo.SmartContract.NefFile>(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAob9XWrEYlohBNhCjWhKIbN4LZscgZzaGEyNTYBAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIJcmlwZW1kMTYwAQABDxv1dasRiWiEE2EKNaEohs3gtmxyCG11cm11cjMyAgABDxv1dasRiWiEE2EKNaEohs3gtmxyD3ZlcmlmeVdpdGhFQ0RzYQQAAQ8b9XWrEYlohBNhCjWhKIbN4LZschFibHMxMjM4MVNlcmlhbGl6ZQEAAQ8b9XWrEYlohBNhCjWhKIbN4LZschNibHMxMjM4MURlc2VyaWFsaXplAQABDxv1dasRiWiEE2EKNaEohs3gtmxyDWJsczEyMzgxRXF1YWwCAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHILYmxzMTIzODFBZGQCAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHILYmxzMTIzODFNdWwDAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIPYmxzMTIzODFQYWlyaW5nAgABDwAAkFcAAXjbKDcAANswIgJAVwABeNsoNwEA2zAiAkBXAAJ5eNsoNwIA2zAiAkBXAAMAF3rbKHl42yg3AwAiAkBXAAMAFnrbKHl42yg3AwAiAkBXAAF4NwQAIgJAVwABeDcFACICQFcAAnl4NwYAIgJAVwACeXg3BwAiAkBXAAN6eXg3CAAiAkBXAAJ5eDcJACICQBCN0V0="));
public static readonly Neo.SmartContract.NefFile Nef = Neo.IO.Helper.AsSerializable<Neo.SmartContract.NefFile>(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAob9XWrEYlohBNhCjWhKIbN4LZscgZzaGEyNTYBAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIJcmlwZW1kMTYwAQABDxv1dasRiWiEE2EKNaEohs3gtmxyCG11cm11cjMyAgABDxv1dasRiWiEE2EKNaEohs3gtmxyD3ZlcmlmeVdpdGhFQ0RzYQQAAQ8b9XWrEYlohBNhCjWhKIbN4LZschFibHMxMjM4MVNlcmlhbGl6ZQEAAQ8b9XWrEYlohBNhCjWhKIbN4LZschNibHMxMjM4MURlc2VyaWFsaXplAQABDxv1dasRiWiEE2EKNaEohs3gtmxyDWJsczEyMzgxRXF1YWwCAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHILYmxzMTIzODFBZGQCAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHILYmxzMTIzODFNdWwDAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIPYmxzMTIzODFQYWlyaW5nAgABDwAAtFcAAXjbKDcAANswIgJAVwABeNsoNwEA2zAiAkBXAAJ5eNsoNwIA2zAiAkBXAAMAF3rbKHl42yg3AwAiAkBXAAMAe3rbKHl42yg3AwAiAkBXAAMAFnrbKHl42yg3AwAiAkBXAAMAenrbKHl42yg3AwAiAkBXAAF4NwQAIgJAVwABeDcFACICQFcAAnl4NwYAIgJAVwACeXg3BwAiAkBXAAN6eXg3CAAiAkBXAAJ5eDcJACICQD/5x9k="));

#endregion

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

/// <summary>
/// Unsafe method
/// </summary>
[DisplayName("secp256k1VerifyKeccakSignatureWithMessage")]
public abstract bool? Secp256k1VerifyKeccakSignatureWithMessage(byte[]? message, ECPoint? pubkey, byte[]? signature);

/// <summary>
/// Unsafe method
/// </summary>
[DisplayName("secp256k1VerifySignatureWithMessage")]
public abstract bool? Secp256k1VerifySignatureWithMessage(byte[]? message, ECPoint? pubkey, byte[]? signature);

/// <summary>
/// Unsafe method
/// </summary>
[DisplayName("secp256r1VerifyKeccakSignatureWithMessage")]
public abstract bool? Secp256r1VerifyKeccakSignatureWithMessage(byte[]? message, ECPoint? pubkey, byte[]? signature);

/// <summary>
/// Unsafe method
/// </summary>
Expand Down

0 comments on commit ac6e7c3

Please sign in to comment.