From 8c9e0c65372b137bbc71b39379eb85a680623e2c Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 12 Jan 2024 02:44:10 +0800 Subject: [PATCH] Adding keccak256 (#2925) * Create codeql.yml * Keccak256 * Delete .github/workflows/codeql.yml * Update src/Neo/SmartContract/Native/CryptoLib.cs * add more keccak256 test cases as required * Create codeql.yml * Keccak256 * Delete .github/workflows/codeql.yml * Update src/Neo/SmartContract/Native/CryptoLib.cs * add more keccak256 test cases as required * HF_Manticore * Fix copyright * Create codeql.yml * Keccak256 * Delete .github/workflows/codeql.yml * Update src/Neo/SmartContract/Native/CryptoLib.cs * add more keccak256 test cases as required * Create codeql.yml * Keccak256 * Delete .github/workflows/codeql.yml * Update src/Neo/SmartContract/Native/CryptoLib.cs * add more keccak256 test cases as required * HF_Manticore * Fix copyright * HF_Manticore * Update CryptoLib.cs * Update CryptoLib.cs * Update UT_CryptoLib.cs * Apply suggestions from code review * clean usings --------- Co-authored-by: Shargon --- src/Neo/Hardfork.cs | 3 +- src/Neo/SmartContract/Native/CryptoLib.cs | 16 ++++ .../SmartContract/Native/UT_CryptoLib.cs | 93 +++++++++++++++++++ 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/src/Neo/Hardfork.cs b/src/Neo/Hardfork.cs index a5decc1d0c..9ef6a63c1c 100644 --- a/src/Neo/Hardfork.cs +++ b/src/Neo/Hardfork.cs @@ -14,6 +14,7 @@ namespace Neo public enum Hardfork : byte { HF_Aspidochelone, - HF_Basilisk + HF_Basilisk, + HF_Cockatrice } } diff --git a/src/Neo/SmartContract/Native/CryptoLib.cs b/src/Neo/SmartContract/Native/CryptoLib.cs index fdc6424c43..a7b822e39c 100644 --- a/src/Neo/SmartContract/Native/CryptoLib.cs +++ b/src/Neo/SmartContract/Native/CryptoLib.cs @@ -11,6 +11,7 @@ using Neo.Cryptography; using Neo.Cryptography.ECC; +using Org.BouncyCastle.Crypto.Digests; using System; using System.Collections.Generic; @@ -64,6 +65,21 @@ public static byte[] Murmur32(byte[] data, uint seed) return murmur.ComputeHash(data); } + /// + /// Computes the hash value for the specified byte array using the keccak256 algorithm. + /// + /// The input to compute the hash code for. + /// Computed hash + [ContractMethod(Hardfork.HF_Cockatrice, CpuFee = 1 << 15)] + public static byte[] Keccak256(byte[] data) + { + KeccakDigest keccak = new(256); + keccak.BlockUpdate(data, 0, data.Length); + byte[] result = new byte[keccak.GetDigestSize()]; + keccak.DoFinal(result, 0); + return result; + } + /// /// Verifies that a digital signature is appropriate for the provided key and message using the ECDSA algorithm. /// diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs index 9e36488031..6f150cca12 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs @@ -15,6 +15,7 @@ using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; +using Org.BouncyCastle.Utilities.Encoders; namespace Neo.UnitTests.SmartContract.Native { @@ -334,5 +335,97 @@ public void TestBls12381ScalarMul_Compat() BLS12381PointType.G2Proj ); } + + /// + /// Keccak256 cases are verified in https://emn178.github.io/online-tools/keccak_256.html + /// + [TestMethod] + public void TestKeccak256_HelloWorld() + { + // Arrange + byte[] inputData = "Hello, World!"u8.ToArray(); + string expectedHashHex = "acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f"; + + // Act + byte[] outputData = CryptoLib.Keccak256(inputData); + string outputHashHex = Hex.ToHexString(outputData); + + // Assert + Assert.AreEqual(expectedHashHex, outputHashHex, "Keccak256 hash did not match expected value for 'Hello, World!'."); + } + [TestMethod] + public void TestKeccak256_Keccak() + { + // Arrange + byte[] inputData = "Keccak"u8.ToArray(); + string expectedHashHex = "868c016b666c7d3698636ee1bd023f3f065621514ab61bf26f062c175fdbe7f2"; + + // Act + byte[] outputData = CryptoLib.Keccak256(inputData); + string outputHashHex = Hex.ToHexString(outputData); + + // Assert + Assert.AreEqual(expectedHashHex, outputHashHex, "Keccak256 hash did not match expected value for 'Keccak'."); + } + + [TestMethod] + public void TestKeccak256_Cryptography() + { + // Arrange + byte[] inputData = "Cryptography"u8.ToArray(); + string expectedHashHex = "53d49d225dd2cfe77d8c5e2112bcc9efe77bea1c7aa5e5ede5798a36e99e2d29"; + + // Act + byte[] outputData = CryptoLib.Keccak256(inputData); + string outputHashHex = Hex.ToHexString(outputData); + + // Assert + Assert.AreEqual(expectedHashHex, outputHashHex, "Keccak256 hash did not match expected value for 'Cryptography'."); + } + + [TestMethod] + public void TestKeccak256_Testing123() + { + // Arrange + byte[] inputData = "Testing123"u8.ToArray(); + string expectedHashHex = "3f82db7b16b0818a1c6b2c6152e265f682d5ebcf497c9aad776ad38bc39cb6ca"; + + // Act + byte[] outputData = CryptoLib.Keccak256(inputData); + string outputHashHex = Hex.ToHexString(outputData); + + // Assert + Assert.AreEqual(expectedHashHex, outputHashHex, "Keccak256 hash did not match expected value for 'Testing123'."); + } + + [TestMethod] + public void TestKeccak256_LongString() + { + // Arrange + byte[] inputData = "This is a longer string for Keccak256 testing purposes."u8.ToArray(); + string expectedHashHex = "24115e5c2359f85f6840b42acd2f7ea47bc239583e576d766fa173bf711bdd2f"; + + // Act + byte[] outputData = CryptoLib.Keccak256(inputData); + string outputHashHex = Hex.ToHexString(outputData); + + // Assert + Assert.AreEqual(expectedHashHex, outputHashHex, "Keccak256 hash did not match expected value for the longer string."); + } + + [TestMethod] + public void TestKeccak256_BlankString() + { + // Arrange + byte[] inputData = ""u8.ToArray(); + string expectedHashHex = "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"; + + // Act + byte[] outputData = CryptoLib.Keccak256(inputData); + string outputHashHex = Hex.ToHexString(outputData); + + // Assert + Assert.AreEqual(expectedHashHex, outputHashHex, "Keccak256 hash did not match expected value for blank string."); + } } }