From 0968c79c53dee4876956b96e10879a09a2e18275 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Tue, 14 Jan 2020 11:53:36 +0900 Subject: [PATCH] Add CryptoBackend --- CHANGES.md | 4 +++ Libplanet/Crypto/CryptoConfig.cs | 19 +++++++++++ Libplanet/Crypto/DefaultCryptoBackend.cs | 34 ++++++++++++++++++++ Libplanet/Crypto/ICryptoBackend.cs | 24 ++++++++++++++ Libplanet/Crypto/PublicKey.cs | 41 +++++++++++------------- 5 files changed, 99 insertions(+), 23 deletions(-) create mode 100644 Libplanet/Crypto/CryptoConfig.cs create mode 100644 Libplanet/Crypto/DefaultCryptoBackend.cs create mode 100644 Libplanet/Crypto/ICryptoBackend.cs diff --git a/CHANGES.md b/CHANGES.md index cfb638abaa3..d185ff33944 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -80,6 +80,9 @@ To be released. - Added `Block.Deserialize(byte[])` method. [[#751]] - Added `Transaction.Deserialize(byte[])` method. [[#751]] - Added `StoreExtension.Copy(this IStore, IStore)` extension method. [[#753]] + - Added `CryptoConfig` class. [[#758]] + - Added `ICryptoBackend` class. [[#758]] + - Added `DefaultCryptoBackend` class. [[#758]] ### Behavioral changes @@ -177,6 +180,7 @@ To be released. [#746]: https://github.com/planetarium/libplanet/pull/746 [#751]: https://github.com/planetarium/libplanet/pull/751 [#753]: https://github.com/planetarium/libplanet/pull/753 +[#758]: https://github.com/planetarium/libplanet/pull/758 Version 0.7.0 diff --git a/Libplanet/Crypto/CryptoConfig.cs b/Libplanet/Crypto/CryptoConfig.cs new file mode 100644 index 00000000000..87dd20639e7 --- /dev/null +++ b/Libplanet/Crypto/CryptoConfig.cs @@ -0,0 +1,19 @@ +namespace Libplanet.Crypto +{ + /// + /// Libplanet cryptography configuration information. + /// + public static class CryptoConfig + { + private static ICryptoBackend _cryptoBackend; + + /// + /// Global cryptography backend to sign and verify messages. + /// + public static ICryptoBackend CryptoBackend + { + get => _cryptoBackend ?? (_cryptoBackend = new DefaultCryptoBackend()); + set => _cryptoBackend = value; + } + } +} diff --git a/Libplanet/Crypto/DefaultCryptoBackend.cs b/Libplanet/Crypto/DefaultCryptoBackend.cs new file mode 100644 index 00000000000..fddd385bd28 --- /dev/null +++ b/Libplanet/Crypto/DefaultCryptoBackend.cs @@ -0,0 +1,34 @@ +using System.IO; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Crypto.Signers; + +namespace Libplanet.Crypto +{ + public class DefaultCryptoBackend : ICryptoBackend + { + public bool Verify( + byte[] messageHash, + byte[] signature, + PublicKey publicKey) + { + try + { + Asn1Sequence asn1Sequence = (Asn1Sequence)Asn1Object.FromByteArray(signature); + + var rs = new[] + { + ((DerInteger)asn1Sequence[0]).Value, + ((DerInteger)asn1Sequence[1]).Value, + }; + var verifier = new ECDsaSigner(); + verifier.Init(false, publicKey.KeyParam); + + return verifier.VerifySignature(messageHash, rs[0], rs[1]); + } + catch (IOException) + { + return false; + } + } + } +} diff --git a/Libplanet/Crypto/ICryptoBackend.cs b/Libplanet/Crypto/ICryptoBackend.cs new file mode 100644 index 00000000000..5acb73d3e65 --- /dev/null +++ b/Libplanet/Crypto/ICryptoBackend.cs @@ -0,0 +1,24 @@ +namespace Libplanet.Crypto +{ + /// + /// Cryptography backend interface. + /// + public interface ICryptoBackend + { + /// + /// Verifies whether a was created from + /// a with the corresponding . + /// + /// A 32 bytes message hash digest hashed with SHA256. + /// A signature that was created from the + /// . + /// used for verification. + /// true if the was created + /// from the with the corresponding + /// . Otherwise false. + bool Verify( + byte[] messageHash, + byte[] signature, + PublicKey publicKey); + } +} diff --git a/Libplanet/Crypto/PublicKey.cs b/Libplanet/Crypto/PublicKey.cs index 4dbf50f6da0..911cb36378d 100644 --- a/Libplanet/Crypto/PublicKey.cs +++ b/Libplanet/Crypto/PublicKey.cs @@ -1,8 +1,7 @@ using System; using System.Diagnostics.Contracts; -using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Security; namespace Libplanet.Crypto { @@ -112,23 +111,7 @@ public byte[] Encrypt(byte[] message) /// from the with the corresponding /// . Otherwise false. [Pure] - public bool Verify(byte[] message, byte[] signature) => - Verify(message, signature, "SHA256withECDSA"); - - private static ECPublicKeyParameters GetECPublicKeyParameters(byte[] bs) - { - var ecParams = PrivateKey.GetECParameters(); - return new ECPublicKeyParameters( - "ECDSA", - ecParams.Curve.DecodePoint(bs), - ecParams - ); - } - - private bool Verify( - byte[] message, - byte[] signature, - string algorithm) + public bool Verify(byte[] message, byte[] signature) { if (message == null) { @@ -140,11 +123,23 @@ private static ECPublicKeyParameters GetECPublicKeyParameters(byte[] bs) throw new ArgumentNullException(nameof(signature)); } - ISigner verifier = SignerUtilities.GetSigner(algorithm); - verifier.Init(false, KeyParam); - verifier.BlockUpdate(message, 0, message.Length); + var h = new Sha256Digest(); + var hashed = new byte[h.GetDigestSize()]; + h.BlockUpdate(message, 0, message.Length); + h.DoFinal(hashed, 0); + h.Reset(); - return verifier.VerifySignature(signature); + return CryptoConfig.CryptoBackend.Verify(hashed, signature, this); + } + + private static ECPublicKeyParameters GetECPublicKeyParameters(byte[] bs) + { + var ecParams = PrivateKey.GetECParameters(); + return new ECPublicKeyParameters( + "ECDSA", + ecParams.Curve.DecodePoint(bs), + ecParams + ); } } }