diff --git a/Docs/docfx.json b/Docs/docfx.json
index dffea54a550..d225a16f1b2 100644
--- a/Docs/docfx.json
+++ b/Docs/docfx.json
@@ -8,7 +8,6 @@
"src/Libplanet.Action/Libplanet.Action.csproj",
"src/Libplanet.Common/Libplanet.Common.csproj",
"src/Libplanet.Crypto/Libplanet.Crypto.csproj",
- "src/Libplanet.Crypto.Secp256k1/Libplanet.Crypto.Secp256k1.csproj",
"tools/Libplanet.Explorer.Cocona/Libplanet.Explorer.Cocona.csproj",
"tools/Libplanet.Extensions.Cocona/Libplanet.Extensions.Cocona.csproj",
"test/Libplanet.Mocks/Libplanet.Mocks.csproj",
diff --git a/Libplanet.sln b/Libplanet.sln
index 6727a518cad..5df0979c1e1 100644
--- a/Libplanet.sln
+++ b/Libplanet.sln
@@ -37,10 +37,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Libplanet.Net", "src\Libpla
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Libplanet.Net.Tests", "test\Libplanet.Net.Tests\Libplanet.Net.Tests.csproj", "{6D7A63C9-16AB-4B7E-B9C0-0956E1E02610}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Libplanet.Crypto.Secp256k1", "src\Libplanet.Crypto.Secp256k1\Libplanet.Crypto.Secp256k1.csproj", "{9F88C871-CB37-4A88-BACF-540AC253C202}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Libplanet.Crypto.Secp256k1.Tests", "test\Libplanet.Crypto.Secp256k1.Tests\Libplanet.Crypto.Secp256k1.Tests.csproj", "{B1A38DDE-5534-4625-A3F2-A585BA7A1198}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Libplanet.Explorer.Cocona", "tools\Libplanet.Explorer.Cocona\Libplanet.Explorer.Cocona.csproj", "{8698E0C2-1A82-43E6-8A26-3D9A825CF574}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Libplanet.Explorer.Cocona.Tests", "test\Libplanet.Explorer.Cocona.Tests\Libplanet.Explorer.Cocona.Tests.csproj", "{F782BC86-9CE6-4F69-8F77-710A399CB54F}"
@@ -391,42 +387,6 @@ Global
{6D7A63C9-16AB-4B7E-B9C0-0956E1E02610}.Release|x64.Build.0 = Release|Any CPU
{6D7A63C9-16AB-4B7E-B9C0-0956E1E02610}.Release|x86.ActiveCfg = Release|Any CPU
{6D7A63C9-16AB-4B7E-B9C0-0956E1E02610}.Release|x86.Build.0 = Release|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.Debug|x64.ActiveCfg = Debug|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.Debug|x64.Build.0 = Debug|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.Debug|x86.ActiveCfg = Debug|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.Debug|x86.Build.0 = Debug|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.ReleaseMono|Any CPU.ActiveCfg = Debug|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.ReleaseMono|Any CPU.Build.0 = Debug|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.ReleaseMono|x64.ActiveCfg = Debug|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.ReleaseMono|x64.Build.0 = Debug|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.ReleaseMono|x86.ActiveCfg = Debug|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.ReleaseMono|x86.Build.0 = Debug|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.Release|Any CPU.Build.0 = Release|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.Release|x64.ActiveCfg = Release|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.Release|x64.Build.0 = Release|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.Release|x86.ActiveCfg = Release|Any CPU
- {9F88C871-CB37-4A88-BACF-540AC253C202}.Release|x86.Build.0 = Release|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.Debug|x64.ActiveCfg = Debug|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.Debug|x64.Build.0 = Debug|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.Debug|x86.ActiveCfg = Debug|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.Debug|x86.Build.0 = Debug|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.ReleaseMono|Any CPU.ActiveCfg = Debug|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.ReleaseMono|Any CPU.Build.0 = Debug|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.ReleaseMono|x64.ActiveCfg = Debug|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.ReleaseMono|x64.Build.0 = Debug|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.ReleaseMono|x86.ActiveCfg = Debug|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.ReleaseMono|x86.Build.0 = Debug|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.Release|Any CPU.Build.0 = Release|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.Release|x64.ActiveCfg = Release|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.Release|x64.Build.0 = Release|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.Release|x86.ActiveCfg = Release|Any CPU
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198}.Release|x86.Build.0 = Release|Any CPU
{8698E0C2-1A82-43E6-8A26-3D9A825CF574}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8698E0C2-1A82-43E6-8A26-3D9A825CF574}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8698E0C2-1A82-43E6-8A26-3D9A825CF574}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -719,8 +679,6 @@ Global
{A43E44E5-F9C1-44BD-A593-419EC113117B} = {B9C00FAF-36CF-463A-83FA-43E6B974AE2E}
{2E17A091-DC29-41FB-ABC8-767BD75FFB07} = {AC908E33-B856-4E23-9F81-B7F7C97A07F9}
{6D7A63C9-16AB-4B7E-B9C0-0956E1E02610} = {B9C00FAF-36CF-463A-83FA-43E6B974AE2E}
- {9F88C871-CB37-4A88-BACF-540AC253C202} = {AC908E33-B856-4E23-9F81-B7F7C97A07F9}
- {B1A38DDE-5534-4625-A3F2-A585BA7A1198} = {B9C00FAF-36CF-463A-83FA-43E6B974AE2E}
{8698E0C2-1A82-43E6-8A26-3D9A825CF574} = {88E7FAF4-CEEC-48B6-9114-71CFE3FC0F50}
{F782BC86-9CE6-4F69-8F77-710A399CB54F} = {B9C00FAF-36CF-463A-83FA-43E6B974AE2E}
{763BAD3E-3244-4E8F-8182-2BF35774262A} = {AC908E33-B856-4E23-9F81-B7F7C97A07F9}
diff --git a/changes/v5.md b/changes/v5.md
index 2c8b415824c..92730337c58 100644
--- a/changes/v5.md
+++ b/changes/v5.md
@@ -374,14 +374,10 @@ below.
The default SDK version for the project has been bumped up to .NET 6.0.
The list of supported SDKs is as follows
- - netstandard2.0
- netstandard2.1
- netcoreapp3.1
- net6.0"
-> Support for `netstandard2.0` is coming to an end soon, please note that
-projects using `netstandard2.0` will be deprecated.
-
The `VersionPrefix` property has been moved from the
*src/Libplanet/Libplanet.csproj* file to the `Directory.Build.props` file.
diff --git a/sdk/node/Libplanet.Node.Executable/Libplanet.Node.Executable.csproj b/sdk/node/Libplanet.Node.Executable/Libplanet.Node.Executable.csproj
index 5da10a9d60b..c8f43a632c2 100644
--- a/sdk/node/Libplanet.Node.Executable/Libplanet.Node.Executable.csproj
+++ b/sdk/node/Libplanet.Node.Executable/Libplanet.Node.Executable.csproj
@@ -27,7 +27,6 @@
-
diff --git a/sdk/node/Libplanet.Node/Actions/PluginLoader.cs b/sdk/node/Libplanet.Node/Actions/PluginLoader.cs
index 352c1e0e12e..65192072bb5 100644
--- a/sdk/node/Libplanet.Node/Actions/PluginLoader.cs
+++ b/sdk/node/Libplanet.Node/Actions/PluginLoader.cs
@@ -10,6 +10,16 @@ internal static class PluginLoader
{
public static IActionLoader LoadActionLoader(string modulePath, string typeName)
{
+ if (Type.GetType(typeName) is { } type)
+ {
+ if (Activator.CreateInstance(type) is not IActionLoader obj)
+ {
+ throw new InvalidOperationException();
+ }
+
+ return obj;
+ }
+
var assembly = LoadAssembly(modulePath);
return Create(assembly, typeName);
}
@@ -17,6 +27,16 @@ public static IActionLoader LoadActionLoader(string modulePath, string typeName)
public static IPolicyActionsRegistry LoadPolicyActionRegistry(
string relativePath, string typeName)
{
+ if (Type.GetType(typeName) is { } type)
+ {
+ if (Activator.CreateInstance(type) is not IPolicyActionsRegistry obj)
+ {
+ throw new InvalidOperationException();
+ }
+
+ return obj;
+ }
+
var assembly = LoadAssembly(relativePath);
return Create(assembly, typeName);
}
diff --git a/sdk/node/Libplanet.Node/Services/ActionService.cs b/sdk/node/Libplanet.Node/Services/ActionService.cs
index 7238781b97d..1c3fdb07a88 100644
--- a/sdk/node/Libplanet.Node/Services/ActionService.cs
+++ b/sdk/node/Libplanet.Node/Services/ActionService.cs
@@ -18,7 +18,8 @@ private static IActionLoader GetActionLoader(ActionOptions options)
{
if (options.ActionLoaderType != string.Empty)
{
- var modulePath = options.ModulePath;
+ var modulePath = options.ModulePath != string.Empty
+ ? Path.GetFullPath(options.ModulePath) : string.Empty;
var actionLoaderType = options.ActionLoaderType;
return PluginLoader.LoadActionLoader(modulePath, actionLoaderType);
}
@@ -30,7 +31,8 @@ private static IPolicyActionsRegistry GetPolicyActionsRegistry(ActionOptions opt
{
if (options.PolicyActionRegistryType != string.Empty)
{
- var modulePath = options.ModulePath;
+ var modulePath = options.ModulePath != string.Empty
+ ? Path.GetFullPath(options.ModulePath) : string.Empty;
var policyActionRegistryType = options.PolicyActionRegistryType;
return PluginLoader.LoadPolicyActionRegistry(modulePath, policyActionRegistryType);
}
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index ce9c961b5b8..b2113b1f8ba 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -3,7 +3,7 @@
- $(TargetFrameworks);netstandard2.0;netstandard2.1;netcoreapp3.1
+ $(TargetFrameworks);netstandard2.1
9
true
false
diff --git a/src/Libplanet.Common/ByteUtil.cs b/src/Libplanet.Common/ByteUtil.cs
index 8ce8134c360..83514f07efb 100644
--- a/src/Libplanet.Common/ByteUtil.cs
+++ b/src/Libplanet.Common/ByteUtil.cs
@@ -6,9 +6,14 @@
using System.Collections.Immutable;
using System.Diagnostics.Contracts;
using System.Globalization;
+using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
+using System.Text;
+using System.Text.Json;
+using Bencodex.Json;
+using Bencodex.Types;
namespace Libplanet.Common
{
@@ -23,6 +28,16 @@ public static class ByteUtil
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
};
+ private static readonly BencodexJsonConverter BencodexJsonConverter = new ();
+ private static readonly JsonSerializerOptions SerializerOptions = new ()
+ {
+ WriteIndented = true,
+ Converters =
+ {
+ BencodexJsonConverter,
+ },
+ };
+
///
/// Converts a hexadecimal string to a mutable array.
///
@@ -232,5 +247,15 @@ public static bool Satisfies(IReadOnlyList hashDigest, long difficulty)
var result = new BigInteger(digestArray);
return result < target;
}
+
+ public static byte[] CreateMessage(IValue value)
+ {
+ using var ms = new MemoryStream();
+ using var writer = new Utf8JsonWriter(ms, new JsonWriterOptions { Indented = true });
+ BencodexJsonConverter.Write(writer, value, SerializerOptions);
+ ms.Position = 0;
+ using var sr = new StreamReader(ms);
+ return Encoding.UTF8.GetBytes(sr.ReadToEnd());
+ }
}
}
diff --git a/src/Libplanet.Common/FixedSizedQueue.cs b/src/Libplanet.Common/FixedSizedQueue.cs
index 16c993a7ea9..9b7e5ae1253 100644
--- a/src/Libplanet.Common/FixedSizedQueue.cs
+++ b/src/Libplanet.Common/FixedSizedQueue.cs
@@ -46,7 +46,7 @@ public FixedSizedQueue(int size)
while (Count > Size)
{
// Ensure we don't exceed the maximum size.
- TryDequeue(out T _);
+ TryDequeue(out T? _);
}
}
}
diff --git a/src/Libplanet.Common/Libplanet.Common.csproj b/src/Libplanet.Common/Libplanet.Common.csproj
index 595138eed71..9c8101404cf 100644
--- a/src/Libplanet.Common/Libplanet.Common.csproj
+++ b/src/Libplanet.Common/Libplanet.Common.csproj
@@ -4,6 +4,7 @@
+
diff --git a/src/Libplanet.Crypto.Secp256k1/Libplanet.Crypto.Secp256k1.csproj b/src/Libplanet.Crypto.Secp256k1/Libplanet.Crypto.Secp256k1.csproj
deleted file mode 100644
index 5296ede1606..00000000000
--- a/src/Libplanet.Crypto.Secp256k1/Libplanet.Crypto.Secp256k1.csproj
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
- 10
- true
- $(NoWarn);NU5104
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Libplanet.Crypto.Secp256k1/Secp256k1CryptoBackend.cs b/src/Libplanet.Crypto.Secp256k1/Secp256k1CryptoBackend.cs
deleted file mode 100644
index f062b56cf6c..00000000000
--- a/src/Libplanet.Crypto.Secp256k1/Secp256k1CryptoBackend.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-using Libplanet.Common;
-using Libplanet.Crypto;
-
-namespace Libplanet.Crypto.Secp256k1;
-
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using System.Security.Cryptography;
-using Libplanet;
-using Secp256k1Net;
-using Libplanet.Crypto;
-
-[SuppressMessage(
- "Minor Code Smell",
- "S101:Types should be named in PascalCase",
- Justification = "Term \"secp256k1\" is a single word.")]
-public class Secp256k1CryptoBackend : ICryptoBackend
- where T : HashAlgorithm
-{
- private readonly Secp256k1 _instance = new Secp256k1();
- private readonly object _instanceLock = new object();
-
- public byte[] Sign(HashDigest messageHash, PrivateKey privateKey)
- {
- lock (_instanceLock)
- {
- var secp256K1Signature = new byte[Secp256k1.SIGNATURE_LENGTH];
- var privateKeyBytes = new byte[Secp256k1.PRIVKEY_LENGTH];
-
- privateKey.ByteArray.CopyTo(
- privateKeyBytes,
- Secp256k1.PRIVKEY_LENGTH - privateKey.ByteArray.Length);
-
- _instance.Sign(
- secp256K1Signature,
- messageHash.ToByteArray(),
- privateKeyBytes);
-
- var signature = new byte[Secp256k1.SERIALIZED_DER_SIGNATURE_MAX_SIZE];
- _instance.SignatureSerializeDer(
- signature,
- secp256K1Signature,
- out int signatureLength);
-
- return signature.Take(signatureLength).ToArray();
- }
- }
-
- public bool Verify(
- HashDigest messageHash,
- byte[] signature,
- PublicKey publicKey)
- {
- lock (_instanceLock)
- {
- var secp256K1Signature = new byte[64];
- _instance.SignatureParseDer(secp256K1Signature, signature);
-
- byte[] secp256K1PublicKey = new byte[64];
- byte[] serializedPublicKey = publicKey.Format(false);
- _instance.PublicKeyParse(secp256K1PublicKey, serializedPublicKey);
-
- return _instance.Verify(
- secp256K1Signature,
- messageHash.ToByteArray(),
- secp256K1PublicKey);
- }
- }
-}
diff --git a/src/Libplanet.Crypto/Address.cs b/src/Libplanet.Crypto/Address.cs
index e0866620e28..47b0159353b 100644
--- a/src/Libplanet.Crypto/Address.cs
+++ b/src/Libplanet.Crypto/Address.cs
@@ -5,13 +5,11 @@
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
-using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Bencodex;
using Bencodex.Types;
using Libplanet.Common;
-using Org.BouncyCastle.Crypto.Digests;
namespace Libplanet.Crypto
{
@@ -259,35 +257,32 @@ public int CompareTo(object? obj) => obj is Address other
private static string ToChecksumAddress(string hex)
{
- byte[] bytes = Encoding.ASCII.GetBytes(hex);
- byte[] hash = CalculateHash(bytes);
- string hashHex = ByteUtil.Hex(hash);
- string address = string.Empty;
-
- for (var i = 0; i < hex.Length; i++)
+ var value = new Nethereum.Util.AddressUtil().ConvertToChecksumAddress(hex);
+ if (value.StartsWith("0x"))
{
- char c = hex[i];
- address += (hashHex[i] >= '8') ? char.ToUpper(c, CultureInfo.InvariantCulture) : c;
+ return value.Substring(2);
}
- return address;
+ return value;
}
- private static byte[] CalculateHash(byte[] value)
+ private static ImmutableArray DeriveAddress(PublicKey key)
{
- var digest = new KeccakDigest(256);
- var output = new byte[digest.GetDigestSize()];
- digest.BlockUpdate(value, 0, value.Length);
- digest.DoFinal(output, 0);
- return output;
+ var initaddr = new Nethereum.Util.Sha3Keccack().CalculateHash(
+ GetPubKeyNoPrefix(key, false));
+ var addr = new byte[initaddr.Length - 12];
+ Array.Copy(initaddr, 12, addr, 0, initaddr.Length - 12);
+ var address = ToChecksumAddress(
+ Nethereum.Hex.HexConvertors.Extensions.HexByteConvertorExtensions.ToHex(addr));
+ return ByteUtil.ParseHexToImmutable(address);
}
- private static ImmutableArray DeriveAddress(PublicKey key)
+ private static byte[] GetPubKeyNoPrefix(PublicKey publicKey, bool compressed = false)
{
- byte[] hashPayload = key.Format(false).Skip(1).ToArray();
- var output = CalculateHash(hashPayload);
-
- return output.Skip(output.Length - Size).ToImmutableArray();
+ var pubKey = publicKey.Format(compressed);
+ var arr = new byte[pubKey.Length - 1];
+ Array.Copy(pubKey, 1, arr, 0, arr.Length);
+ return arr;
}
private static ImmutableArray DeriveAddress(string hex)
diff --git a/src/Libplanet.Crypto/CryptoConfig.cs b/src/Libplanet.Crypto/CryptoConfig.cs
index dbe14798343..393cd5c4c11 100644
--- a/src/Libplanet.Crypto/CryptoConfig.cs
+++ b/src/Libplanet.Crypto/CryptoConfig.cs
@@ -1,5 +1,3 @@
-using System.Security.Cryptography;
-
namespace Libplanet.Crypto
{
///
@@ -7,14 +5,14 @@ namespace Libplanet.Crypto
///
public static class CryptoConfig
{
- private static ICryptoBackend? _cryptoBackend;
+ private static ICryptoBackend? _cryptoBackend;
///
/// Global cryptography backend to sign and verify messages.
///
- public static ICryptoBackend CryptoBackend
+ public static ICryptoBackend CryptoBackend
{
- get => _cryptoBackend ??= new DefaultCryptoBackend();
+ get => _cryptoBackend ??= new DefaultCryptoBackend();
set => _cryptoBackend = value;
}
}
diff --git a/src/Libplanet.Crypto/DefaultCryptoBackend.cs b/src/Libplanet.Crypto/DefaultCryptoBackend.cs
index e08b80745cc..49ccaf1b0b1 100644
--- a/src/Libplanet.Crypto/DefaultCryptoBackend.cs
+++ b/src/Libplanet.Crypto/DefaultCryptoBackend.cs
@@ -1,69 +1,89 @@
-using System.IO;
-using System.Security.Cryptography;
-using Libplanet.Common;
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Crypto.Signers;
-using Org.BouncyCastle.Math;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Nethereum.Util;
+using Secp256k1Net;
+using ByteUtil = Libplanet.Common.ByteUtil;
namespace Libplanet.Crypto
{
- public class DefaultCryptoBackend : ICryptoBackend
- where T : HashAlgorithm
+ public class DefaultCryptoBackend : ICryptoBackend
{
- public byte[] Sign(HashDigest messageHash, PrivateKey privateKey)
- {
- var h = new Sha256Digest();
- var kCalculator = new HMacDsaKCalculator(h);
- var signer = new ECDsaSigner(kCalculator);
- signer.Init(true, privateKey.KeyParam);
- BigInteger[] rs = signer.GenerateSignature(messageHash.ToByteArray());
- var r = rs[0];
- var s = rs[1];
+ private const int Offset = 27;
- BigInteger otherS = privateKey.KeyParam.Parameters.N.Subtract(s);
- if (s.CompareTo(otherS) == 1)
+ public byte[] Sign(byte[] message, PrivateKey privateKey)
+ {
+ lock (PrivateKey._secpLock)
{
- s = otherS;
- }
+ using var secp = new Secp256k1();
+ var keccak = new Sha3Keccack();
+ var messageHash = HashPrefixedMessage(message);
+ var keyBytes = privateKey.ToByteArray();
+ var sig1 = new byte[Secp256k1.UNSERIALIZED_SIGNATURE_SIZE];
+ var sig2 = new byte[Secp256k1.SERIALIZED_SIGNATURE_SIZE];
+ var signature = new byte[Secp256k1.UNSERIALIZED_SIGNATURE_SIZE];
+ if (!secp.SignRecoverable(sig1, messageHash, keyBytes))
+ {
+ throw new InvalidOperationException("Failed to sign the message.");
+ }
- using var bos = new MemoryStream(72);
- using (var seq = new DerSequenceGenerator(bos))
- {
- seq.AddObject(new DerInteger(r));
- seq.AddObject(new DerInteger(s));
- }
+ if (!secp.RecoverableSignatureSerializeCompact(sig2, out var recoverId, sig1))
+ {
+ throw new InvalidOperationException("Failed to serialize the signature.");
+ }
- return bos.ToArray();
+ Array.Copy(sig2, signature, sig2.Length);
+ signature[sig2.Length] = Convert.ToByte(recoverId + Offset);
+ return signature;
+ }
}
- public bool Verify(
- HashDigest messageHash,
- byte[] signature,
- PublicKey publicKey)
+ public bool Verify(byte[] message, byte[] signature, PublicKey publicKey)
+ => Verify(message, signature, publicKey.Address);
+
+ public bool Verify(byte[] message, byte[] signature, Address signer)
{
- try
+ lock (PrivateKey._secpLock)
{
- Asn1Sequence asn1Sequence = (Asn1Sequence)Asn1Object.FromByteArray(signature);
+ using var secp = new Secp256k1();
+ var keccak = new Sha3Keccack();
+ var publicKeyOutput = new byte[Secp256k1.PUBKEY_LENGTH];
+ var serializedKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH];
+ var messageHash = HashPrefixedMessage(message);
+ var recoverId = signature[signature.Length - 1] - Offset;
- var rs = new[]
+ var sig2 = new byte[Secp256k1.UNSERIALIZED_SIGNATURE_SIZE];
+ if (!secp.RecoverableSignatureParseCompact(sig2, signature, recoverId))
{
- ((DerInteger)asn1Sequence[0]).Value,
- ((DerInteger)asn1Sequence[1]).Value,
- };
- var verifier = new ECDsaSigner();
- verifier.Init(false, publicKey.KeyParam);
+ return false;
+ }
- return verifier.VerifySignature(messageHash.ToByteArray(), rs[0], rs[1]);
- }
- catch (IOException)
- {
- return false;
- }
- catch (Asn1ParsingException)
- {
- return false;
+ if (!secp.Recover(publicKeyOutput, sig2, messageHash))
+ {
+ return false;
+ }
+
+ if (!secp.PublicKeySerialize(serializedKey, publicKeyOutput))
+ {
+ return false;
+ }
+
+ return signer.Equals(new PublicKey(serializedKey).Address);
}
}
+
+ private static byte[] HashPrefixedMessage(byte[] message)
+ {
+ var bytePrefix = ByteUtil.ParseHex("19");
+ var textBytePrefix = Encoding.UTF8.GetBytes(
+ "Ethereum Signed Message:\n" + message.Length);
+ var byteList = new List(
+ bytePrefix.Length + textBytePrefix.Length + message.Length);
+
+ byteList.AddRange(bytePrefix);
+ byteList.AddRange(textBytePrefix);
+ byteList.AddRange(message);
+ return new DefaultMessageHasher().Hash(byteList.ToArray());
+ }
}
}
diff --git a/src/Libplanet.Crypto/ICryptoBackend.cs b/src/Libplanet.Crypto/ICryptoBackend.cs
index 3c2b48ee1d4..b371765f9db 100644
--- a/src/Libplanet.Crypto/ICryptoBackend.cs
+++ b/src/Libplanet.Crypto/ICryptoBackend.cs
@@ -1,47 +1,39 @@
using System;
-using System.Security.Cryptography;
-using Libplanet.Common;
namespace Libplanet.Crypto
{
///
/// Cryptography backend interface.
///
- /// A which corresponds to a digest.
- ///
- public interface ICryptoBackend
- where T : HashAlgorithm
+ public interface ICryptoBackend
{
///
- /// Creates a signature from with the corresponding
+ /// Creates a signature from with the corresponding
/// .
///
- /// A 32 bytes message hash digest hashed with SHA256 to sign.
+ /// A 32 bytes message hash digest hashed with SHA256 to sign.
///
/// to sign
- /// .
+ /// .
///
- /// Created a signature from with the corresponding
+ /// Created a signature from with the corresponding
/// .
///
- byte[] Sign(HashDigest messageHash, PrivateKey privateKey);
+ byte[] Sign(byte[] message, PrivateKey privateKey);
///
/// Verifies whether a was created from
- /// a with the corresponding .
+ /// a with the corresponding .
///
- /// A 32 bytes message hash digest hashed with SHA256.
+ /// A 32 bytes message hash digest hashed with SHA256.
/// A signature that was created from the
- /// .
- /// used for verification.
+ /// .
+ /// used for verification.
/// if the was created
- /// from the with the corresponding
+ /// from the with the corresponding
/// . Otherwise .
/// If any exception is thrown, the given
/// is considered as invalid.
- bool Verify(
- HashDigest messageHash,
- byte[] signature,
- PublicKey publicKey);
+ bool Verify(byte[] message, byte[] signature, Address signer);
}
}
diff --git a/src/Libplanet.Crypto/Libplanet.Crypto.csproj b/src/Libplanet.Crypto/Libplanet.Crypto.csproj
index 7ea3441fd03..899431a39cf 100644
--- a/src/Libplanet.Crypto/Libplanet.Crypto.csproj
+++ b/src/Libplanet.Crypto/Libplanet.Crypto.csproj
@@ -4,7 +4,9 @@
-
+
+
+
diff --git a/src/Libplanet.Crypto/PrivateKey.cs b/src/Libplanet.Crypto/PrivateKey.cs
index 93c91b995ea..8e1e89fa1ce 100644
--- a/src/Libplanet.Crypto/PrivateKey.cs
+++ b/src/Libplanet.Crypto/PrivateKey.cs
@@ -1,20 +1,13 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using Libplanet.Common;
-using Org.BouncyCastle.Asn1.Sec;
-using Org.BouncyCastle.Asn1.X9;
-using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Crypto.Generators;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
-using Org.BouncyCastle.Math.EC;
-using Org.BouncyCastle.Security;
-using ECPoint = Org.BouncyCastle.Math.EC.ECPoint;
+using Secp256k1Net;
namespace Libplanet.Crypto
{
@@ -42,7 +35,9 @@ namespace Libplanet.Crypto
///
public class PrivateKey : IEquatable
{
+ internal static readonly object _secpLock = new object();
private const int KeyByteSize = 32;
+ private readonly ImmutableArray _bytes;
private PublicKey? _publicKey;
///
@@ -50,7 +45,7 @@ public class PrivateKey : IEquatable
/// It can be analogous to creating a new account in a degree.
///
public PrivateKey()
- : this(GenerateKeyParam())
+ : this(GenerateBytes())
{
}
@@ -66,16 +61,14 @@ public PrivateKey()
/// A valid array for a can be encoded
/// using property.
///
- public PrivateKey(IReadOnlyList privateKey)
- : this(privateKey is byte[] ba ? ba : privateKey.ToArray(), informedConsent: true)
+ public PrivateKey(byte[] privateKey)
+ : this(privateKey.ToImmutableArray())
+ {
+ }
+
+ public PrivateKey(in ImmutableArray immutableBytes)
+ : this(immutableBytes, verify: true)
{
- if (privateKey.Count != KeyByteSize)
- {
- throw new ArgumentOutOfRangeException(
- nameof(privateKey),
- $"The key must be {KeyByteSize} bytes."
- );
- }
}
///
@@ -91,27 +84,18 @@ public PrivateKey(IReadOnlyList privateKey)
/// Thrown when the given string is
/// not a valid hexadecimal string.
public PrivateKey(string hex)
- : this(unverifiedKey: GenerateBytesFromHexString(hex), informedConsent: true)
+ : this(GenerateBytesFromHexString(hex), verify: true)
{
}
- public PrivateKey(byte[] unverifiedKey, bool informedConsent)
- : this(GenerateKeyFromBytes(unverifiedKey))
+ private PrivateKey(in ImmutableArray bytes, bool verify)
{
- // The `informedConsent` parameter mainly purposes to prevent this overload from
- // being chosen instead of PrivatKey(IReadOnly) by mistake.
- if (!informedConsent)
+ if (verify && !VerifyBytes(bytes))
{
- throw new ArgumentException(
- nameof(informedConsent),
- "The caller should ensure the key is valid and safe enough."
- );
+ throw new ArgumentException("Invalid private key.", nameof(bytes));
}
- }
- private PrivateKey(ECPrivateKeyParameters keyParam)
- {
- KeyParam = keyParam;
+ _bytes = bytes;
}
///
@@ -124,10 +108,13 @@ public PublicKey PublicKey
{
if (_publicKey is null)
{
- ECDomainParameters ecParams = GetECParameters();
- ECPoint q = ecParams.G.Multiply(KeyParam.D);
- var kp = new ECPublicKeyParameters("ECDSA", q, ecParams);
- _publicKey = new PublicKey(kp);
+ lock (_secpLock)
+ {
+ using var secp256k1 = new Secp256k1();
+ var publicKey = new byte[Secp256k1.PUBKEY_LENGTH];
+ secp256k1.PublicKeyCreate(publicKey, _bytes.ToArray());
+ _publicKey = new PublicKey(publicKey, verify: false);
+ }
}
return _publicKey;
@@ -160,8 +147,6 @@ public PublicKey PublicKey
[Pure]
public ImmutableArray ByteArray => ToByteArray().ToImmutableArray();
- internal ECPrivateKeyParameters KeyParam { get; }
-
public static bool operator ==(PrivateKey left, PrivateKey right) => left.Equals(right);
public static bool operator !=(PrivateKey left, PrivateKey right) => !left.Equals(right);
@@ -180,20 +165,23 @@ public PublicKey PublicKey
/// not a valid hexadecimal string.
[Pure]
public static PrivateKey FromString(string hex)
- {
- return new PrivateKey(
- unverifiedKey: GenerateBytesFromHexString(hex),
- informedConsent: true
- );
- }
+ => new PrivateKey(GenerateBytesFromHexString(hex), verify: true);
- public bool Equals(PrivateKey? other) => KeyParam.Equals(other?.KeyParam);
+ public bool Equals(PrivateKey? other)
+ => other is not null && _bytes.SequenceEqual(other._bytes);
public override bool Equals(object? obj) => obj is PrivateKey other && Equals(other);
- public override int GetHashCode() =>
- unchecked(ByteUtil.CalculateHashCode(ToByteArray()) * 397 ^
- KeyParam.GetHashCode());
+ public override int GetHashCode()
+ {
+ HashCode hash = default;
+ for (var i = 0; i < _bytes.Length; i++)
+ {
+ hash.Add(_bytes[i]);
+ }
+
+ return hash.ToHashCode();
+ }
///
/// Creates a signature from the given .
@@ -226,8 +214,8 @@ public override int GetHashCode() =>
///
public byte[] Sign(byte[] message)
{
- HashDigest hashed = HashDigest.DeriveFrom(message);
- return CryptoConfig.CryptoBackend.Sign(hashed, this);
+ // HashDigest hashed = HashDigest.DeriveFrom(message);
+ return CryptoConfig.CryptoBackend.Sign(message, this);
}
///
@@ -253,8 +241,8 @@ public byte[] Sign(byte[] message)
///
public ImmutableArray Sign(ImmutableArray message)
{
- HashDigest hashed = HashDigest.DeriveFrom(message);
- byte[] sig = CryptoConfig.CryptoBackend.Sign(hashed, this);
+ // HashDigest hashed = HashDigest.DeriveFrom(message);
+ byte[] sig = CryptoConfig.CryptoBackend.Sign(message.ToArray(), this);
return Unsafe.As>(ref sig);
}
@@ -320,21 +308,14 @@ public ImmutableArray Decrypt(ImmutableArray ciphertext) =>
[Pure]
public SymmetricKey ExchangeKey(PublicKey publicKey)
{
- ECPoint p = CalculatePoint(publicKey.KeyParam);
- BigInteger x = p.AffineXCoord.ToBigInteger();
- BigInteger y = p.AffineYCoord.ToBigInteger();
-
- byte[] xbuf = x.ToByteArrayUnsigned();
- var ybuf = new byte[] { (byte)(y.TestBit(0) ? 0x03 : 0x02) };
-
- var hash = new Sha256Digest();
- var result = new byte[hash.GetDigestSize()];
-
- hash.BlockUpdate(ybuf, 0, ybuf.Length);
- hash.BlockUpdate(xbuf, 0, xbuf.Length);
- hash.DoFinal(result, 0);
+ lock (_secpLock)
+ {
+ using var secp256k1 = new Secp256k1();
+ var secret = new byte[Secp256k1.SECRET_LENGTH];
+ secp256k1.Ecdh(secret, publicKey.Raw.ToArray(), _bytes.ToArray());
- return new SymmetricKey(result);
+ return new SymmetricKey(secret);
+ }
}
///
@@ -359,71 +340,45 @@ public SymmetricKey ExchangeKey(PublicKey publicKey)
///
///
[Pure]
- public byte[] ToByteArray() =>
- KeyParam.D.ToByteArrayUnsigned();
+ public byte[] ToByteArray() => _bytes.ToArray();
- internal static ECDomainParameters GetECParameters()
+ internal static byte[] GetPublicKey(in ImmutableArray raw, bool compress)
{
- return GetECParameters("secp256k1");
- }
-
- private static ECDomainParameters GetECParameters(string name)
- {
- X9ECParameters ps = SecNamedCurves.GetByName(name);
- return new ECDomainParameters(ps.Curve, ps.G, ps.N, ps.H);
- }
-
- private static ECPrivateKeyParameters GenerateKeyParam()
- {
- var gen = new ECKeyPairGenerator();
- var secureRandom = new SecureRandom();
- ECDomainParameters ecParams = GetECParameters();
- var keyGenParam =
- new ECKeyGenerationParameters(ecParams, secureRandom);
- gen.Init(keyGenParam);
-
- const int maxTries = 3000;
- int tries = 0;
- ECPrivateKeyParameters result;
-
- while (tries < maxTries)
+ lock (_secpLock)
{
- result = (ECPrivateKeyParameters)gen.GenerateKeyPair().Private;
- if (result.D.ToByteArrayUnsigned().Length == KeyByteSize)
+ using var secp256k1 = new Secp256k1();
+ var length = compress
+ ? Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH
+ : Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH;
+ var flag = compress
+ ? Flags.SECP256K1_EC_COMPRESSED : Flags.SECP256K1_EC_UNCOMPRESSED;
+ var publicKey = new byte[length];
+ if (!secp256k1.PublicKeySerialize(publicKey, raw.ToArray(), flag))
{
- return result;
+ throw new NotSupportedException("Failed to serialize a public key.");
}
- tries++;
+ return publicKey;
}
-
- throw new GenerateKeyParamTriesExceedException(
- "Can't find appropriate parameter for private key" +
- $"(maxTries: {maxTries})"
- );
}
- private static ECPrivateKeyParameters GenerateKeyFromBytes(byte[] privateKey)
+ private static byte[] GenerateBytes()
{
- if (privateKey.All(b => b.Equals(0x00)))
+ lock (_secpLock)
{
- throw new ArgumentException("Every bytes in Private key is zero value.");
+ using var secp256k1 = new Secp256k1();
+ using var rnd = RandomNumberGenerator.Create();
+ var privateKey = new byte[Secp256k1.PRIVKEY_LENGTH];
+ do
+ {
+ rnd.GetBytes(privateKey);
+ }
+ while (!secp256k1.SecretKeyVerify(privateKey));
+ return privateKey;
}
-
- var param = new ECPrivateKeyParameters(
- "ECDSA",
- new BigInteger(1, privateKey),
- GetECParameters()
- );
-
- // For sanity check.
-#pragma warning disable SA1312, S1481
- var _ = new PrivateKey(param).PublicKey;
-#pragma warning restore SA1312, S1481
- return param;
}
- private static byte[] GenerateBytesFromHexString(string hex)
+ private static ImmutableArray GenerateBytesFromHexString(string hex)
{
byte[] bytes = ByteUtil.ParseHex(hex);
if (bytes.Length != KeyByteSize)
@@ -434,45 +389,16 @@ private static byte[] GenerateBytesFromHexString(string hex)
);
}
- return bytes;
+ return bytes.ToImmutableArray();
}
- private ECPoint CalculatePoint(ECPublicKeyParameters pubKeyParams)
+ private static bool VerifyBytes(in ImmutableArray bytes)
{
- ECDomainParameters dp = KeyParam.Parameters;
- if (!dp.Equals(pubKeyParams.Parameters))
+ lock (_secpLock)
{
- throw new InvalidOperationException(
- "ECDH public key has wrong domain parameters"
- );
+ using var secp256k1 = new Secp256k1();
+ return bytes.Length == KeyByteSize && secp256k1.SecretKeyVerify(bytes.ToArray());
}
-
- BigInteger d = KeyParam.D;
-
- ECPoint q = dp.Curve.DecodePoint(pubKeyParams.Q.GetEncoded(true));
- if (q.IsInfinity)
- {
- throw new InvalidOperationException(
- "Infinity is not a valid public key for ECDH"
- );
- }
-
- BigInteger h = dp.H;
- if (!h.Equals(BigInteger.One))
- {
- d = dp.H.ModInverse(dp.N).Multiply(d).Mod(dp.N);
- q = ECAlgorithms.ReferenceMultiply(q, h);
- }
-
- ECPoint p = q.Multiply(d).Normalize();
- if (p.IsInfinity)
- {
- throw new InvalidOperationException(
- "Infinity is not a valid agreement value for ECDH"
- );
- }
-
- return p;
}
}
}
diff --git a/src/Libplanet.Crypto/PublicKey.cs b/src/Libplanet.Crypto/PublicKey.cs
index 65a3fca8239..7496de7c09b 100644
--- a/src/Libplanet.Crypto/PublicKey.cs
+++ b/src/Libplanet.Crypto/PublicKey.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel;
+using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
@@ -10,7 +11,7 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Libplanet.Common;
-using Org.BouncyCastle.Crypto.Parameters;
+using Secp256k1Net;
namespace Libplanet.Crypto
{
@@ -36,13 +37,15 @@ namespace Libplanet.Crypto
[JsonConverter(typeof(PublicKeyJsonConverter))]
public class PublicKey : IEquatable
{
+ private readonly ImmutableArray _bytes;
+
///
/// Creates a instance from the given
- /// array (i.e., ),
+ /// array (i.e., ),
/// which encodes a valid
/// ECDSA public key.
///
- /// A valid array that
+ /// A valid array that
/// encodes an ECDSA public key. It can be either compressed or
/// not.
/// A valid array for
@@ -50,14 +53,26 @@ public class PublicKey : IEquatable
/// method.
///
///
- public PublicKey(IReadOnlyList publicKey)
- : this(GetECPublicKeyParameters(publicKey is byte[] ba ? ba : publicKey.ToArray()))
+ public PublicKey(byte[] bytes)
+ : this(bytes, verify: true)
{
}
- internal PublicKey(ECPublicKeyParameters keyParam)
+ internal PublicKey(byte[] bytes, bool verify)
{
- KeyParam = keyParam;
+ if (verify)
+ {
+ if (!TryGetPublicKey(bytes, out var publicKey))
+ {
+ throw new ArgumentException("Invalid public key bytes.", nameof(bytes));
+ }
+
+ _bytes = publicKey!.ToImmutableArray();
+ }
+ else
+ {
+ _bytes = bytes.ToImmutableArray();
+ }
}
///
@@ -65,7 +80,7 @@ internal PublicKey(ECPublicKeyParameters keyParam)
///
public Address Address => new Address(this);
- internal ECPublicKeyParameters KeyParam { get; }
+ internal ImmutableArray Raw => _bytes;
public static bool operator ==(PublicKey left, PublicKey right) => left.Equals(right);
@@ -83,13 +98,43 @@ internal PublicKey(ECPublicKeyParameters keyParam)
/// is not a valid hexadecimal string.
///
public static PublicKey FromHex(string hex) =>
- new PublicKey(ByteUtil.ParseHex(hex));
+ new PublicKey(ByteUtil.ParseHex(hex), verify: true);
- public bool Equals(PublicKey? other) => KeyParam.Equals(other?.KeyParam);
+ public static bool Verify(
+ Address signer, ImmutableArray message, ImmutableArray signature)
+ {
+ if (signature.IsDefaultOrEmpty)
+ {
+ return false;
+ }
+
+ try
+ {
+ // var hashed = HashDigest.DeriveFrom(message);
+ return CryptoConfig.CryptoBackend.Verify(
+ message.ToArray(), signature.ToArray(), signer);
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+
+ public bool Equals(PublicKey? other)
+ => other is not null && _bytes.SequenceEqual(other._bytes);
public override bool Equals(object? obj) => obj is PublicKey other && Equals(other);
- public override int GetHashCode() => KeyParam.GetHashCode();
+ public override int GetHashCode()
+ {
+ HashCode hash = default;
+ foreach (byte b in _bytes)
+ {
+ hash.Add(b);
+ }
+
+ return hash.ToHashCode();
+ }
///
/// Encodes this public key into a mutable array representation.
@@ -105,8 +150,7 @@ public static PublicKey FromHex(string hex) =>
///
///
[Pure]
- public byte[] Format(bool compress) =>
- KeyParam.Q.GetEncoded(compress);
+ public byte[] Format(bool compress) => PrivateKey.GetPublicKey(_bytes, compress);
///
/// Encodes this public key into a immutable array representation.
@@ -124,6 +168,9 @@ public byte[] Format(bool compress) =>
public ImmutableArray ToImmutableArray(bool compress) =>
Format(compress).ToImmutableArray();
+ [Pure]
+ public byte[] ToArray() => Format(false);
+
///
/// Encrypts a plaintext to a ciphertext, which can be decrypted
/// with the corresponding .
@@ -180,41 +227,7 @@ public ImmutableArray Encrypt(ImmutableArray message) =>
/// Otherwise .
[Pure]
public bool Verify(IReadOnlyList message, IReadOnlyList signature)
- {
- if (message == null)
- {
- throw new ArgumentNullException(nameof(message));
- }
-
- if (signature == null)
- {
- throw new ArgumentNullException(nameof(signature));
- }
-
- if (signature is ImmutableArray i ? i.IsDefaultOrEmpty : !signature.Any())
- {
- return false;
- }
-
- try
- {
- HashDigest hashed = message switch
- {
- byte[] ma => HashDigest.DeriveFrom(ma),
- ImmutableArray im => HashDigest.DeriveFrom(im),
- _ => HashDigest.DeriveFrom(message.ToArray()),
- };
- return CryptoConfig.CryptoBackend.Verify(
- hashed,
- signature is byte[] ba ? ba : signature.ToArray(),
- publicKey: this
- );
- }
- catch (Exception)
- {
- return false;
- }
- }
+ => Verify(Address, message.ToImmutableArray(), signature.ToImmutableArray());
///
/// Gets the public key's hexadecimal representation in compressed form.
@@ -228,14 +241,21 @@ public bool Verify(IReadOnlyList message, IReadOnlyList signature)
///
public override string ToString() => ToHex(true);
- private static ECPublicKeyParameters GetECPublicKeyParameters(byte[] bs)
+ private static bool TryGetPublicKey(
+ byte[] bytes, [MaybeNullWhen(false)] out byte[] publicKey)
{
- var ecParams = PrivateKey.GetECParameters();
- return new ECPublicKeyParameters(
- "ECDSA",
- ecParams.Curve.DecodePoint(bs),
- ecParams
- );
+ lock (PrivateKey._secpLock)
+ {
+ using var secp256k1 = new Secp256k1();
+ publicKey = new byte[Secp256k1.PUBKEY_LENGTH];
+ if (secp256k1.PublicKeyParse(publicKey, bytes))
+ {
+ return true;
+ }
+
+ publicKey = null;
+ return false;
+ }
}
}
diff --git a/src/Libplanet.Crypto/SymmetricKey.cs b/src/Libplanet.Crypto/SymmetricKey.cs
index 5cfbcce5a43..84a0b8803b1 100644
--- a/src/Libplanet.Crypto/SymmetricKey.cs
+++ b/src/Libplanet.Crypto/SymmetricKey.cs
@@ -3,12 +3,8 @@
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
+using System.Security.Cryptography;
using Libplanet.Common;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Engines;
-using Org.BouncyCastle.Crypto.Modes;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Security;
namespace Libplanet.Crypto
{
@@ -23,11 +19,11 @@ namespace Libplanet.Crypto
///
public class SymmetricKey : IEquatable
{
- private const int KeyBitSize = 256;
- private const int MacBitSize = 128;
- private const int NonceBitSize = 128;
+ private const int KeyByteSize = 32; // 256 bits
+ private const int TagByteSize = 16; // 128 bits
+ private const int NonceByteSize = 12; // 128 bits
- private readonly SecureRandom _secureRandom;
+ private readonly RandomNumberGenerator _secureRandom;
private readonly byte[] _key;
@@ -51,12 +47,12 @@ public class SymmetricKey : IEquatable
///
public SymmetricKey(byte[] key)
{
- _secureRandom = new SecureRandom();
+ _secureRandom = RandomNumberGenerator.Create();
- if (key == null || key.Length != KeyBitSize / 8)
+ if (key == null || key.Length != KeyByteSize)
{
throw new ArgumentException(
- $"Key needs to be {KeyBitSize} bit!",
+ $"Key needs to be {KeyByteSize} bytes!",
nameof(key));
}
@@ -113,33 +109,29 @@ public bool Equals(SymmetricKey? other)
///
///
[Pure]
- public byte[] Encrypt(byte[] message, byte[]? nonSecret = null)
+ public byte[] Encrypt(byte[] message, byte[] nonSecret)
{
- var nonce = new byte[NonceBitSize / 8];
- _secureRandom.NextBytes(nonce, 0, nonce.Length);
-
- nonSecret = nonSecret ?? new byte[] { };
-
- var cipher = new GcmBlockCipher(new AesEngine());
- var parameters = new AeadParameters(
- new KeyParameter(_key), MacBitSize, nonce, nonSecret
- );
- cipher.Init(true, parameters);
-
- var cipherText = new byte[cipher.GetOutputSize(message.Length)];
- int len =
- cipher.ProcessBytes(message, 0, message.Length, cipherText, 0);
- cipher.DoFinal(cipherText, len);
-
- using var combinedStream = new MemoryStream();
- using (var binaryWriter = new BinaryWriter(combinedStream))
- {
- binaryWriter.Write(nonSecret);
- binaryWriter.Write(nonce);
- binaryWriter.Write(cipherText);
- }
-
- return combinedStream.ToArray();
+#if NETSTANDARD2_0_OR_GREATER
+ using var aes = new AesGcm(_key);
+#else
+ using var aes = new AesGcm(_key, tagSizeInBytes: TagByteSize);
+#endif
+ byte[] nonce = new byte[NonceByteSize];
+ _secureRandom.GetBytes(nonce);
+
+ byte[] ciphertext = new byte[message.Length];
+ byte[] tag = new byte[TagByteSize];
+ _secureRandom.GetBytes(nonce);
+
+ aes.Encrypt(nonce, message, ciphertext, tag, nonSecret);
+
+ using var resultStream = new MemoryStream();
+ using var writer = new BinaryWriter(resultStream);
+ writer.Write(nonSecret);
+ writer.Write(nonce);
+ writer.Write(ciphertext);
+ writer.Write(tag);
+ return resultStream.ToArray();
}
///
@@ -164,48 +156,30 @@ public byte[] Encrypt(byte[] message, byte[]? nonSecret = null)
[Pure]
public byte[] Decrypt(byte[] ciphertext, int nonSecretLength = 0)
{
- if (ciphertext == null || ciphertext.Length == 0)
- {
- throw new ArgumentException(
- "Encrypted Message Required!",
- nameof(ciphertext));
- }
-
- using var cipherStream = new MemoryStream(ciphertext);
- using var cipherReader = new BinaryReader(cipherStream);
- byte[] nonSecretPayload = cipherReader.ReadBytes(
- nonSecretLength
- );
- byte[] nonce = cipherReader.ReadBytes(NonceBitSize / 8);
-
- var cipher = new GcmBlockCipher(new AesEngine());
- var parameters = new AeadParameters(
- new KeyParameter(_key),
- MacBitSize,
- nonce,
- nonSecretPayload);
- cipher.Init(false, parameters);
-
- byte[] cipherText = cipherReader.ReadBytes(
- ciphertext.Length - nonSecretLength - nonce.Length
- );
- var plainText =
- new byte[cipher.GetOutputSize(cipherText.Length)];
-
+#if NETSTANDARD2_0_OR_GREATER
+ using var aes = new AesGcm(_key);
+#else
+ using var aes = new AesGcm(_key, tagSizeInBytes: TagByteSize);
+#endif
+ using var inputStream = new MemoryStream(ciphertext);
+ using var reader = new BinaryReader(inputStream);
+ var nonSecretPayload = reader.ReadBytes(nonSecretLength);
+
+ byte[] nonce = reader.ReadBytes(NonceByteSize);
+ byte[] encryptedMessage = reader.ReadBytes(
+ ciphertext.Length - nonSecretLength - nonce.Length - TagByteSize);
+ byte[] tag = reader.ReadBytes(TagByteSize);
+
+ byte[] decryptedMessage = new byte[encryptedMessage.Length];
try
{
- int len = cipher.ProcessBytes(
- cipherText, 0, cipherText.Length, plainText, 0
- );
- cipher.DoFinal(plainText, len);
- return plainText;
+ aes.Decrypt(nonce, encryptedMessage, tag, decryptedMessage, nonSecretPayload);
+ return decryptedMessage;
}
- catch (InvalidCipherTextException)
+ catch (Exception e)
{
- throw new InvalidCiphertextException(
- "The ciphertext is invalid. " +
- "Ciphertext may not have been encrypted with " +
- "the corresponding public key");
+ var message = "Failed to decrypt the ciphertext.";
+ throw new InvalidCiphertextException(message, e);
}
}
diff --git a/src/Libplanet.Net/AppProtocolVersion.cs b/src/Libplanet.Net/AppProtocolVersion.cs
index 1fb63805380..4e65555bea5 100644
--- a/src/Libplanet.Net/AppProtocolVersion.cs
+++ b/src/Libplanet.Net/AppProtocolVersion.cs
@@ -7,7 +7,6 @@
using Bencodex.Types;
using Libplanet.Common;
using Libplanet.Crypto;
-using NetMQ;
namespace Libplanet.Net
{
@@ -280,16 +279,10 @@ public override string ToString() => string.Format(
[Pure]
private static byte[] GetMessage(int version, IValue? extra)
{
- byte[] msg = NetworkOrderBitsConverter.GetBytes(version);
- if (!(extra is null))
- {
- byte[] extraBytes = _codec.Encode(extra);
- int versionLength = msg.Length;
- Array.Resize(ref msg, versionLength + extraBytes.Length);
- extraBytes.CopyTo(msg, versionLength);
- }
-
- return msg;
+ var list = new List(
+ new Integer(version),
+ extra is null ? Null.Value : extra);
+ return ByteUtil.CreateMessage(list);
}
}
}
diff --git a/src/Libplanet.Net/BoundPeer.cs b/src/Libplanet.Net/BoundPeer.cs
index 64d2b99b530..1ffb055b20c 100644
--- a/src/Libplanet.Net/BoundPeer.cs
+++ b/src/Libplanet.Net/BoundPeer.cs
@@ -1,6 +1,7 @@
using System;
using System.Diagnostics.Contracts;
using System.Globalization;
+using System.Linq;
using System.Net;
using Bencodex;
using Bencodex.Types;
@@ -59,7 +60,7 @@ internal BoundPeer(
private BoundPeer(Bencodex.Types.Dictionary bencoded)
: this(
- new PublicKey(((Binary)bencoded[PublicKeyKey]).ByteArray),
+ new PublicKey(((Binary)bencoded[PublicKeyKey]).ByteArray.ToArray()),
new DnsEndPoint(
(Text)bencoded[EndPointHostKey], (Integer)bencoded[EndPointPortKey]),
bencoded[PublicIpAddressKey] is Text text ? IPAddress.Parse(text) : null)
diff --git a/src/Libplanet.Store/BlockSet.cs b/src/Libplanet.Store/BlockSet.cs
index 59b45b83673..a7882d109d7 100644
--- a/src/Libplanet.Store/BlockSet.cs
+++ b/src/Libplanet.Store/BlockSet.cs
@@ -157,7 +157,7 @@ public IEnumerator> GetEnumerator()
private Block? GetBlock(BlockHash key)
{
- if (_cache.TryGet(key, out Block cached))
+ if (_cache.TryGet(key, out Block? cached))
{
if (_store.ContainsBlock(key))
{
diff --git a/src/Libplanet.Types/Blocks/BlockMarshaler.cs b/src/Libplanet.Types/Blocks/BlockMarshaler.cs
index 1ca963c4cd0..0cac497335f 100644
--- a/src/Libplanet.Types/Blocks/BlockMarshaler.cs
+++ b/src/Libplanet.Types/Blocks/BlockMarshaler.cs
@@ -175,7 +175,7 @@ public static BlockMetadata UnmarshalBlockMetadata(Dictionary marshaled)
PublicKey? publicKey = null;
if (marshaled.ContainsKey(PublicKeyKey))
{
- publicKey = new PublicKey(((Binary)marshaled[PublicKeyKey]).ByteArray);
+ publicKey = new PublicKey(((Binary)marshaled[PublicKeyKey]).ByteArray.ToArray());
miner = publicKey.Address;
}
else
diff --git a/src/Libplanet.Types/Consensus/Validator.cs b/src/Libplanet.Types/Consensus/Validator.cs
index 539e7b13e06..4fea566a280 100644
--- a/src/Libplanet.Types/Consensus/Validator.cs
+++ b/src/Libplanet.Types/Consensus/Validator.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Numerics;
using System.Text.Json.Serialization;
using Bencodex;
@@ -53,7 +54,7 @@ public Validator(Bencodex.Types.IValue bencoded)
private Validator(Bencodex.Types.Dictionary bencoded)
: this(
- new PublicKey(((Binary)bencoded[PublicKeyKey]).ByteArray),
+ new PublicKey(((Binary)bencoded[PublicKeyKey]).ByteArray.ToArray()),
(Integer)bencoded[PowerKey])
{
}
diff --git a/src/Libplanet.Types/Consensus/VoteMetadata.cs b/src/Libplanet.Types/Consensus/VoteMetadata.cs
index cf9adbe39a2..73904072d2c 100644
--- a/src/Libplanet.Types/Consensus/VoteMetadata.cs
+++ b/src/Libplanet.Types/Consensus/VoteMetadata.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Immutable;
using System.Globalization;
+using System.Linq;
using System.Numerics;
using System.Text.Json.Serialization;
using Bencodex;
@@ -126,7 +127,7 @@ private VoteMetadata(Bencodex.Types.Dictionary bencoded)
TimestampFormat,
CultureInfo.InvariantCulture),
validatorPublicKey: new PublicKey(
- ((Binary)bencoded[ValidatorPublicKeyKey]).ByteArray),
+ ((Binary)bencoded[ValidatorPublicKeyKey]).ByteArray.ToArray()),
validatorPower: bencoded.ContainsKey(ValidatorPowerKey)
? (Integer)bencoded[ValidatorPowerKey]
: (Integer?)null,
diff --git a/src/Libplanet.Types/Tx/ITxSigningMetadata.cs b/src/Libplanet.Types/Tx/ITxSigningMetadata.cs
index 83b88e67adb..4a003af8dd1 100644
--- a/src/Libplanet.Types/Tx/ITxSigningMetadata.cs
+++ b/src/Libplanet.Types/Tx/ITxSigningMetadata.cs
@@ -24,12 +24,5 @@ public interface ITxSigningMetadata : IEquatable
/// from the .
///
Address Signer { get; }
-
- ///
- /// A of the account who signs this transaction.
- /// The address is always corresponding to this for each transaction.
- /// This cannot be .
- ///
- PublicKey PublicKey { get; }
}
}
diff --git a/src/Libplanet.Types/Tx/Transaction.cs b/src/Libplanet.Types/Tx/Transaction.cs
index 9d54135779c..f0c5b8a990b 100644
--- a/src/Libplanet.Types/Tx/Transaction.cs
+++ b/src/Libplanet.Types/Tx/Transaction.cs
@@ -156,9 +156,6 @@ private set
///
public DateTimeOffset Timestamp => _unsignedTx.Timestamp;
- ///
- public PublicKey PublicKey => _unsignedTx.PublicKey;
-
///
public BlockHash? GenesisHash => _unsignedTx.GenesisHash;
@@ -319,7 +316,7 @@ private static Transaction Create(
actions,
maxGasPrice,
gasLimit);
- var signMeta = new TxSigningMetadata(privateKey.PublicKey, nonce);
+ var signMeta = new TxSigningMetadata(privateKey.Address, nonce);
var invoice = new TxInvoice(
draftInvoice.GenesisHash,
draftInvoice.UpdatedAddresses,
diff --git a/src/Libplanet.Types/Tx/TransactionExtensions.cs b/src/Libplanet.Types/Tx/TransactionExtensions.cs
index b9fe0737250..b65a7dd30fd 100644
--- a/src/Libplanet.Types/Tx/TransactionExtensions.cs
+++ b/src/Libplanet.Types/Tx/TransactionExtensions.cs
@@ -85,7 +85,7 @@ public static Transaction Sign(
PrivateKey privateKey,
long nonce)
=>
- invoice.Combine(new TxSigningMetadata(privateKey.PublicKey, nonce)).Sign(privateKey);
+ invoice.Combine(new TxSigningMetadata(privateKey.Address, nonce)).Sign(privateKey);
///
/// A instance.
diff --git a/src/Libplanet.Types/Tx/TxMarshaler.cs b/src/Libplanet.Types/Tx/TxMarshaler.cs
index 22d400780d8..d728df2f039 100644
--- a/src/Libplanet.Types/Tx/TxMarshaler.cs
+++ b/src/Libplanet.Types/Tx/TxMarshaler.cs
@@ -2,9 +2,13 @@
using System.Collections.Immutable;
using System.Diagnostics.Contracts;
using System.Globalization;
+using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
+using System.Text;
+using System.Text.Json;
using Bencodex;
+using Bencodex.Json;
using Bencodex.Types;
using Libplanet.Crypto;
using Libplanet.Types.Assets;
@@ -22,11 +26,20 @@ public static class TxMarshaler
private static readonly Binary GasLimitKey = new Binary(new byte[] { 0x6c }); // 'l'
private static readonly Binary NonceKey = new Binary(new byte[] { 0x6e }); // 'n'
private static readonly Binary SignerKey = new Binary(new byte[] { 0x73 }); // 's'
- private static readonly Binary PublicKeyKey = new Binary(new byte[] { 0x70 }); // 'p'
private static readonly Binary SignatureKey = new Binary(new byte[] { 0x53 }); // 'S'
private static readonly Binary ActionsKey = new Binary(new byte[] { 0x61 }); // 'a'
private static readonly Codec Codec = new Codec();
+ private static readonly BencodexJsonConverter BencodexJsonConverter = new ();
+ private static readonly JsonSerializerOptions SerializerOptions = new ()
+ {
+ WriteIndented = true,
+ Converters =
+ {
+ BencodexJsonConverter,
+ },
+ };
+
[Pure]
public static Bencodex.Types.Dictionary MarshalTxInvoice(this ITxInvoice invoice)
{
@@ -70,23 +83,33 @@ public static Bencodex.Types.Dictionary MarshalTxSigningMetadata(
this ITxSigningMetadata metadata
) => Dictionary.Empty
.Add(NonceKey, metadata.Nonce)
- .Add(SignerKey, metadata.Signer.Bencoded)
- .Add(PublicKeyKey, metadata.PublicKey.ToImmutableArray(compress: false));
+ .Add(SignerKey, metadata.Signer.Bencoded);
[Pure]
- public static Bencodex.Types.Dictionary MarshalUnsignedTx(this IUnsignedTx unsignedTx) =>
- (Bencodex.Types.Dictionary)unsignedTx.MarshalTxInvoice()
+ public static Dictionary MarshalUnsignedTx(this IUnsignedTx unsignedTx)
+ => (Dictionary)unsignedTx.MarshalTxInvoice()
.AddRange(unsignedTx.MarshalTxSigningMetadata());
[Pure]
- public static Bencodex.Types.Dictionary MarshalTransaction(
- this Transaction transaction) =>
- transaction.MarshalUnsignedTx().Add(SignatureKey, transaction.Signature);
+ public static string SerializeUnsignedTxToJson(this IUnsignedTx unsignedTx)
+ {
+ var dict = unsignedTx.MarshalUnsignedTx();
+ using var ms = new MemoryStream();
+ using var writer = new Utf8JsonWriter(ms, new JsonWriterOptions { Indented = true });
+ BencodexJsonConverter.Write(writer, dict, SerializerOptions);
+ ms.Position = 0;
+ using var sr = new StreamReader(ms);
+ return sr.ReadToEnd();
+ }
+
+ [Pure]
+ public static Dictionary MarshalTransaction(this Transaction transaction)
+ => transaction.MarshalUnsignedTx().Add(SignatureKey, transaction.Signature);
[Pure]
public static ImmutableArray SerializeUnsignedTx(this IUnsignedTx unsignedTx)
{
- Bencodex.Types.Dictionary dict = unsignedTx.MarshalUnsignedTx();
+ Dictionary dict = unsignedTx.MarshalUnsignedTx();
byte[] encoded = Codec.Encode(dict);
ImmutableArray movedBytes =
Unsafe.As>(ref encoded);
@@ -125,8 +148,8 @@ public static ITxSigningMetadata UnmarshalTxSigningMetadata(
Bencodex.Types.Dictionary dictionary
) =>
new TxSigningMetadata(
- nonce: (Bencodex.Types.Integer)dictionary[NonceKey],
- publicKey: new PublicKey(((Binary)dictionary[PublicKeyKey]).ByteArray)
+ signer: new Address(dictionary[SignerKey]),
+ nonce: (Bencodex.Types.Integer)dictionary[NonceKey]
);
[Pure]
@@ -169,6 +192,24 @@ public static IUnsignedTx DeserializeUnsignedTx(byte[] bytes)
$"but {node.GetType().Name} given.");
}
+ [Pure]
+ public static IUnsignedTx DeserializeUnsignedTxFromJson(string json)
+ {
+ using var ms = new MemoryStream(Encoding.UTF8.GetBytes(json));
+ var reader = new Utf8JsonReader(ms.ToArray());
+ var value = BencodexJsonConverter.Read(ref reader, typeof(IValue), SerializerOptions)
+ ?? throw new InvalidOperationException("Failed to parse the unsigned transaction.");
+ if (value is Dictionary dict)
+ {
+ return UnmarshalUnsignedTx(dict);
+ }
+
+ throw new DecodingException(
+ $"Expected a {typeof(Bencodex.Types.Dictionary).FullName}, " +
+ $"but {value.GetType().Name} given."
+ );
+ }
+
[Pure]
public static IUnsignedTx DeserializeUnsignedTx(ImmutableArray bytes)
{
diff --git a/src/Libplanet.Types/Tx/TxMetadata.cs b/src/Libplanet.Types/Tx/TxMetadata.cs
index 411f292a416..487a75f8783 100644
--- a/src/Libplanet.Types/Tx/TxMetadata.cs
+++ b/src/Libplanet.Types/Tx/TxMetadata.cs
@@ -23,18 +23,17 @@ public sealed class TxMetadata
private static readonly Binary SignerKey = new Binary(new byte[] { 0x73 }); // 's'
private static readonly Binary GenesisHashKey = new Binary(new byte[] { 0x67 }); // 'g'
private static readonly Binary UpdatedAddressesKey = new Binary(new byte[] { 0x75 }); // 'u'
- private static readonly Binary PublicKeyKey = new Binary(new byte[] { 0x70 }); // 'p'
private static readonly Binary TimestampKey = new Binary(new byte[] { 0x74 }); // 't'
///
/// Creates a instance with a .
/// Other fields can be set using property setters.
///
- /// Configures and .
+ /// Configures .
///
- public TxMetadata(PublicKey publicKey)
+ public TxMetadata(Address signer)
{
- PublicKey = publicKey;
+ Signer = signer;
}
///
@@ -50,7 +49,7 @@ public TxMetadata(ITransaction metadata)
Nonce = metadata.Nonce;
GenesisHash = metadata.GenesisHash;
UpdatedAddresses = metadata.UpdatedAddresses;
- PublicKey = metadata.PublicKey;
+ Signer = metadata.Signer;
Timestamp = metadata.Timestamp;
}
@@ -72,7 +71,7 @@ public TxMetadata(Bencodex.Types.Dictionary dictionary)
UpdatedAddresses = ((List)dictionary[UpdatedAddressesKey])
.Select(v => new Address(v))
.ToImmutableHashSet();
- PublicKey = new PublicKey(((Binary)dictionary[PublicKeyKey]).ByteArray);
+ Signer = new Address(((Binary)dictionary[SignerKey]).ByteArray);
Timestamp = DateTimeOffset.ParseExact(
(Text)dictionary[TimestampKey],
TimestampFormat,
@@ -89,10 +88,9 @@ public TxMetadata(Bencodex.Types.Dictionary dictionary)
///
/// A of the account who signs this transaction.
- /// This is derived from the .
///
/// This is automatically derived from .
- public Address Signer => new Address(PublicKey);
+ public Address Signer { get; }
///
/// An approximated list of addresses whose states would be affected by actions in this
@@ -107,13 +105,6 @@ public TxMetadata(Bencodex.Types.Dictionary dictionary)
///
public DateTimeOffset Timestamp { get; set; } = DateTimeOffset.UtcNow;
- ///
- /// A of the account who signs this transaction.
- /// The address is always corresponding to this
- /// for each transaction. This cannot be .
- ///
- public PublicKey PublicKey { get; }
-
///
/// A value of the genesis which this transaction is made
/// from. This can be iff the transaction is contained in
@@ -133,7 +124,6 @@ public Bencodex.Types.Dictionary ToBencodex()
.Add(NonceKey, Nonce)
.Add(SignerKey, Signer.Bencoded)
.Add(UpdatedAddressesKey, updatedAddresses)
- .Add(PublicKeyKey, PublicKey.ToImmutableArray(compress: false))
.Add(TimestampKey, timestamp);
if (GenesisHash is { } genesisHash)
@@ -155,7 +145,6 @@ public override string ToString()
(UpdatedAddresses.Any()
? $"\n {string.Join("\n ", UpdatedAddresses)};\n"
: ";\n") +
- $" {nameof(PublicKey)} = {PublicKey},\n" +
$" {nameof(Timestamp)} = {Timestamp},\n" +
$" {nameof(GenesisHash)} = {GenesisHash?.ToString() ?? "(null)"},\n" +
"}";
diff --git a/src/Libplanet.Types/Tx/TxSigningMetadata.cs b/src/Libplanet.Types/Tx/TxSigningMetadata.cs
index 8ce71cd106f..9b0943824a6 100644
--- a/src/Libplanet.Types/Tx/TxSigningMetadata.cs
+++ b/src/Libplanet.Types/Tx/TxSigningMetadata.cs
@@ -16,11 +16,11 @@ public sealed class TxSigningMetadata : ITxSigningMetadata, IEquatable
/// Creates a new instance by filling data for its fields.
///
- /// The value for .
+ /// The value for .
/// The value for .
/// Thrown when the given
/// is less than 0.
- public TxSigningMetadata(PublicKey publicKey, long nonce)
+ public TxSigningMetadata(Address signer, long nonce)
{
if (nonce < 0)
{
@@ -29,10 +29,15 @@ public TxSigningMetadata(PublicKey publicKey, long nonce)
$"The nonce must be greater than or equal to 0, but {nonce} was given.");
}
- PublicKey = publicKey;
+ Signer = signer;
Nonce = nonce;
}
+ public TxSigningMetadata(PublicKey publicKey, long nonce)
+ : this(publicKey.Address, nonce)
+ {
+ }
+
///
/// Creates a new instance by copying the fields from
/// the given .
@@ -40,16 +45,13 @@ public TxSigningMetadata(PublicKey publicKey, long nonce)
/// The instance to copy
/// fields from.
public TxSigningMetadata(ITxSigningMetadata signingMetadata)
- : this(signingMetadata.PublicKey, signingMetadata.Nonce)
+ : this(signingMetadata.Signer, signingMetadata.Nonce)
{
}
///
/// This is automatically derived from .
- public Address Signer => new Address(PublicKey);
-
- ///
- public PublicKey PublicKey { get; }
+ public Address Signer { get; }
///
public long Nonce { get; }
@@ -57,7 +59,7 @@ public TxSigningMetadata(ITxSigningMetadata signingMetadata)
///
[Pure]
bool IEquatable.Equals(ITxSigningMetadata? other) =>
- other is { } o && o.PublicKey.Equals(PublicKey) && o.Nonce == Nonce;
+ other is { } o && o.Signer.Equals(Signer) && o.Nonce == Nonce;
///
[Pure]
@@ -71,7 +73,7 @@ public override bool Equals(object? obj) =>
///
[Pure]
- public override int GetHashCode() => HashCode.Combine(PublicKey, Nonce);
+ public override int GetHashCode() => HashCode.Combine(Signer, Nonce);
///
[Pure]
@@ -80,7 +82,6 @@ public override string ToString()
return nameof(TxMetadata) + " {\n" +
$" {nameof(Nonce)} = {Nonce},\n" +
$" {nameof(Signer)} = {Signer},\n" +
- $" {nameof(PublicKey)} = {PublicKey},\n" +
"}";
}
}
diff --git a/src/Libplanet.Types/Tx/UnsignedTx.cs b/src/Libplanet.Types/Tx/UnsignedTx.cs
index be6afe80f34..65cb875e8b0 100644
--- a/src/Libplanet.Types/Tx/UnsignedTx.cs
+++ b/src/Libplanet.Types/Tx/UnsignedTx.cs
@@ -1,10 +1,14 @@
using System;
using System.Collections.Immutable;
using System.Diagnostics.Contracts;
+using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
+using System.Text;
+using System.Text.Json;
using System.Text.Json.Serialization;
using Bencodex;
+using Bencodex.Json;
using Libplanet.Crypto;
using Libplanet.Types.Assets;
using Libplanet.Types.Blocks;
@@ -90,20 +94,17 @@ public UnsignedTx(ITxInvoice invoice, ITxSigningMetadata signingMetadata)
///
public Address Signer => _signingMetadata.Signer;
- ///
- public PublicKey PublicKey => _signingMetadata.PublicKey;
-
///
/// Creates a signature for this transaction with the given .
///
/// The private key to sign this transaction.
/// A signature for this transaction.
/// Thrown when the given
- /// does not correspond to the of this transaction.
+ /// does not correspond to the of this transaction.
[Pure]
public ImmutableArray CreateSignature(PrivateKey privateKey)
{
- if (!privateKey.PublicKey.Equals(PublicKey))
+ if (!privateKey.Address.Equals(Signer))
{
throw new ArgumentException(
"The given private key does not correspond to the public key.",
@@ -125,7 +126,7 @@ public ImmutableArray CreateSignature(PrivateKey privateKey)
/// this transaction, otherwise .
[Pure]
public bool VerifySignature(ImmutableArray signature) =>
- PublicKey.Verify(CreateMessage(), signature);
+ PublicKey.Verify(Signer, CreateMessage().ToImmutableArray(), signature);
///
[Pure]
@@ -175,12 +176,14 @@ public override string ToString()
$" {nameof(Actions)} = {indentedActions},\n" +
$" {nameof(Nonce)} = {Nonce},\n" +
$" {nameof(Signer)} = {Signer},\n" +
- $" {nameof(PublicKey)} = {PublicKey},\n" +
"}";
}
[Pure]
- private byte[] CreateMessage() =>
- _codec.Encode(this.MarshalUnsignedTx());
+ private byte[] CreateMessage()
+ {
+ var json = this.SerializeUnsignedTxToJson();
+ return Encoding.UTF8.GetBytes(json);
+ }
}
}
diff --git a/src/Libplanet/Consensus/Maj23Metadata.cs b/src/Libplanet/Consensus/Maj23Metadata.cs
index 7b2eacebe38..6b5267364c0 100644
--- a/src/Libplanet/Consensus/Maj23Metadata.cs
+++ b/src/Libplanet/Consensus/Maj23Metadata.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Immutable;
using System.Globalization;
+using System.Linq;
using System.Text.Json.Serialization;
using Bencodex;
using Bencodex.Types;
@@ -80,7 +81,7 @@ public Maj23Metadata(Dictionary encoded)
TimestampFormat,
CultureInfo.InvariantCulture),
validatorPublicKey: new PublicKey(
- ((Binary)encoded[ValidatorPublicKeyKey]).ByteArray),
+ ((Binary)encoded[ValidatorPublicKeyKey]).ByteArray.ToArray()),
flag: (VoteFlag)(int)(Integer)encoded[FlagKey])
{
}
diff --git a/src/Libplanet/Consensus/ProposalClaimMetadata.cs b/src/Libplanet/Consensus/ProposalClaimMetadata.cs
index 3c6064cd796..f648f5695d7 100644
--- a/src/Libplanet/Consensus/ProposalClaimMetadata.cs
+++ b/src/Libplanet/Consensus/ProposalClaimMetadata.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Immutable;
using System.Globalization;
+using System.Linq;
using System.Text.Json.Serialization;
using Bencodex;
using Bencodex.Types;
@@ -91,7 +92,7 @@ public ProposalClaimMetadata(Dictionary encoded)
TimestampFormat,
CultureInfo.InvariantCulture),
validatorPublicKey: new PublicKey(
- ((Binary)encoded[ValidatorPublicKeyKey]).ByteArray))
+ ((Binary)encoded[ValidatorPublicKeyKey]).ByteArray.ToArray()))
{
}
#pragma warning restore SA1118
diff --git a/src/Libplanet/Consensus/ProposalMetadata.cs b/src/Libplanet/Consensus/ProposalMetadata.cs
index 0b251391279..9892323358c 100644
--- a/src/Libplanet/Consensus/ProposalMetadata.cs
+++ b/src/Libplanet/Consensus/ProposalMetadata.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Immutable;
using System.Globalization;
+using System.Linq;
using System.Text.Json.Serialization;
using Bencodex;
using Bencodex.Types;
@@ -108,7 +109,7 @@ public ProposalMetadata(Dictionary encoded)
TimestampFormat,
CultureInfo.InvariantCulture),
validatorPublicKey: new PublicKey(
- ((Binary)encoded[ValidatorPublicKeyKey]).ByteArray),
+ ((Binary)encoded[ValidatorPublicKeyKey]).ByteArray.ToArray()),
marshaledBlock: ((Binary)encoded[BlockKey]).ToByteArray(),
validRound: (Integer)encoded[ValidRoundKey])
{
diff --git a/src/Libplanet/Consensus/VoteSetBitsMetadata.cs b/src/Libplanet/Consensus/VoteSetBitsMetadata.cs
index e56a5f1f1ba..c78f38a93ba 100644
--- a/src/Libplanet/Consensus/VoteSetBitsMetadata.cs
+++ b/src/Libplanet/Consensus/VoteSetBitsMetadata.cs
@@ -87,7 +87,7 @@ public VoteSetBitsMetadata(Dictionary encoded)
TimestampFormat,
CultureInfo.InvariantCulture),
validatorPublicKey: new PublicKey(
- ((Binary)encoded[ValidatorPublicKeyKey]).ByteArray),
+ ((Binary)encoded[ValidatorPublicKeyKey]).ByteArray.ToArray()),
flag: (VoteFlag)(int)(Integer)encoded[FlagKey],
voteBits: ((List)encoded[VoteBitsKey])
.Select(bit => (bool)(Bencodex.Types.Boolean)bit))
diff --git a/src/Libplanet/KeyStore/ProtectedPrivateKey.cs b/src/Libplanet/KeyStore/ProtectedPrivateKey.cs
index d0d2a3ae233..d63b7468cb9 100644
--- a/src/Libplanet/KeyStore/ProtectedPrivateKey.cs
+++ b/src/Libplanet/KeyStore/ProtectedPrivateKey.cs
@@ -322,10 +322,7 @@ public PrivateKey Unprotect(string passphrase)
ImmutableArray encKey = MakeEncryptionKey(derivedKey);
ImmutableArray plaintext = Cipher.Decrypt(encKey, Ciphertext);
- var key = new PrivateKey(
- unverifiedKey: plaintext.ToBuilder().ToArray(),
- informedConsent: true
- );
+ var key = new PrivateKey(plaintext.ToBuilder().ToArray());
Address actualAddress = key.Address;
if (!Address.Equals(actualAddress))
{
diff --git a/src/Libplanet/Libplanet.csproj b/src/Libplanet/Libplanet.csproj
index e7c328d29bc..4a159ca6530 100644
--- a/src/Libplanet/Libplanet.csproj
+++ b/src/Libplanet/Libplanet.csproj
@@ -30,15 +30,10 @@ https://docs.libplanet.io/
-
+
-
-
-
-
diff --git a/test/Libplanet.Crypto.Secp256k1.Tests/Libplanet.Crypto.Secp256k1.Tests.csproj b/test/Libplanet.Crypto.Secp256k1.Tests/Libplanet.Crypto.Secp256k1.Tests.csproj
deleted file mode 100644
index e9b0254b78d..00000000000
--- a/test/Libplanet.Crypto.Secp256k1.Tests/Libplanet.Crypto.Secp256k1.Tests.csproj
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test/Libplanet.Crypto.Secp256k1.Tests/Secp256k1CryptoBackendTest.cs b/test/Libplanet.Crypto.Secp256k1.Tests/Secp256k1CryptoBackendTest.cs
deleted file mode 100644
index b26e0bcd3de..00000000000
--- a/test/Libplanet.Crypto.Secp256k1.Tests/Secp256k1CryptoBackendTest.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using Libplanet.Common;
-using Libplanet.Crypto;
-
-namespace Libplanet.Crypto.Secp256k1.Tests;
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-using Libplanet.Crypto;
-using Libplanet.Crypto.Secp256k1;
-using Xunit;
-
-public class Secp256k1CryptoBackendTest
-{
- public static IEnumerable
diff --git a/tools/Libplanet.Tools/Program.cs b/tools/Libplanet.Tools/Program.cs
index 4d1d3d2b3fd..f0a8561a5d3 100644
--- a/tools/Libplanet.Tools/Program.cs
+++ b/tools/Libplanet.Tools/Program.cs
@@ -5,7 +5,6 @@ namespace Libplanet.Tools;
using System.Security.Cryptography;
using System.Threading.Tasks;
using Cocona;
-using Libplanet.Crypto.Secp256k1;
using Libplanet.Extensions.Cocona.Commands;
using Libplanet.Extensions.Cocona.Extensions;
using CryptoConfig = Libplanet.Crypto.CryptoConfig;
@@ -29,16 +28,6 @@ public class Program
public static Task Main(string[] args)
{
- try
- {
- CryptoConfig.CryptoBackend = new Secp256k1CryptoBackend();
- }
- catch (Exception)
- {
- // If it fails to load the Secp256k1CryptoBackend for any reason
- // fall back to the DefaultCryptoBackend instead.
- }
-
return CoconaLiteApp.CreateHostBuilder()
.ConfigureServices(services =>
{