From 70913b1666371fd401981f0e4dca895aa293780a Mon Sep 17 00:00:00 2001 From: s2quake Date: Wed, 5 Mar 2025 13:24:12 +0900 Subject: [PATCH] feat: Introduce Nethereum crypto --- Libplanet.sln | 21 +++++++++ .../Libplanet.Crypto.Nethereum.csproj | 22 ++++++++++ .../NethereumCryptoBackend.cs | 44 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 src/Libplanet.Crypto.Nethereum/Libplanet.Crypto.Nethereum.csproj create mode 100644 src/Libplanet.Crypto.Nethereum/NethereumCryptoBackend.cs diff --git a/Libplanet.sln b/Libplanet.sln index 6727a518ca..0cfd1d4d94 100644 --- a/Libplanet.sln +++ b/Libplanet.sln @@ -81,6 +81,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Libplanet.Node.Executable", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Libplanet.Node.Tests", "sdk\node\Libplanet.Node.Tests\Libplanet.Node.Tests.csproj", "{C050C5F0-8A40-4CB1-9715-A55EBF94FBF2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Libplanet.Crypto.Nethereum", "src\Libplanet.Crypto.Nethereum\Libplanet.Crypto.Nethereum.csproj", "{42801CB6-D452-408C-B0A5-970D8D997B38}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -697,6 +699,24 @@ Global {C050C5F0-8A40-4CB1-9715-A55EBF94FBF2}.Release|x64.Build.0 = Release|Any CPU {C050C5F0-8A40-4CB1-9715-A55EBF94FBF2}.Release|x86.ActiveCfg = Release|Any CPU {C050C5F0-8A40-4CB1-9715-A55EBF94FBF2}.Release|x86.Build.0 = Release|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.Debug|x64.ActiveCfg = Debug|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.Debug|x64.Build.0 = Debug|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.Debug|x86.ActiveCfg = Debug|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.Debug|x86.Build.0 = Debug|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.ReleaseMono|Any CPU.ActiveCfg = Debug|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.ReleaseMono|Any CPU.Build.0 = Debug|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.ReleaseMono|x64.ActiveCfg = Debug|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.ReleaseMono|x64.Build.0 = Debug|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.ReleaseMono|x86.ActiveCfg = Debug|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.ReleaseMono|x86.Build.0 = Debug|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.Release|Any CPU.Build.0 = Release|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.Release|x64.ActiveCfg = Release|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.Release|x64.Build.0 = Release|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.Release|x86.ActiveCfg = Release|Any CPU + {42801CB6-D452-408C-B0A5-970D8D997B38}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -737,6 +757,7 @@ Global {704BA731-9C70-4CBE-A607-1A2E1FB73753} = {8CA69CC9-3415-4484-9342-88D495AE2FF6} {A0EAD8F0-B7A3-4112-9F3F-2D9922A500BA} = {8CA69CC9-3415-4484-9342-88D495AE2FF6} {C050C5F0-8A40-4CB1-9715-A55EBF94FBF2} = {8CA69CC9-3415-4484-9342-88D495AE2FF6} + {42801CB6-D452-408C-B0A5-970D8D997B38} = {AC908E33-B856-4E23-9F81-B7F7C97A07F9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DB552D2A-94E1-4A1C-9F3E-E0097C6158CD} diff --git a/src/Libplanet.Crypto.Nethereum/Libplanet.Crypto.Nethereum.csproj b/src/Libplanet.Crypto.Nethereum/Libplanet.Crypto.Nethereum.csproj new file mode 100644 index 0000000000..090dfa8bc6 --- /dev/null +++ b/src/Libplanet.Crypto.Nethereum/Libplanet.Crypto.Nethereum.csproj @@ -0,0 +1,22 @@ + + + + 10 + true + $(NoWarn);NU5104 + + + + + + + + + + + + + + + + diff --git a/src/Libplanet.Crypto.Nethereum/NethereumCryptoBackend.cs b/src/Libplanet.Crypto.Nethereum/NethereumCryptoBackend.cs new file mode 100644 index 0000000000..1e0674012e --- /dev/null +++ b/src/Libplanet.Crypto.Nethereum/NethereumCryptoBackend.cs @@ -0,0 +1,44 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Security.Cryptography; +using Libplanet; +using Libplanet.Common; +using Libplanet.Crypto; +using EthECKey = Nethereum.Signer.EthECKey; +using EthereumMessageSigner = Nethereum.Signer.EthereumMessageSigner; + +namespace Libplanet.Crypto.Nethereum; + +public class NethereumCryptoBackend : ICryptoBackend + where T : HashAlgorithm +{ + private readonly EthereumMessageSigner _signer = new EthereumMessageSigner(); + private readonly object _instanceLock = new object(); + + public byte[] Sign(HashDigest messageHash, PrivateKey privateKey) + { + lock (_instanceLock) + { + var key = new EthECKey(privateKey.ToByteArray(), isPrivate: true); + var signature = _signer.Sign(messageHash.ToByteArray(), key); + if (signature.StartsWith("0x")) + { + signature = signature.Substring(2); + } + + return ByteUtil.ParseHex(signature); + } + } + + public bool Verify( + HashDigest messageHash, + byte[] signature, + PublicKey publicKey) + { + lock (_instanceLock) + { + var address = _signer.EcRecover(messageHash.ToByteArray(), ByteUtil.Hex(signature)); + return publicKey.Address.Equals(new Address(address)); + } + } +}