Skip to content

Commit

Permalink
Add CryptoBackend
Browse files Browse the repository at this point in the history
  • Loading branch information
earlbread committed Jan 14, 2020
1 parent 524209d commit 0968c79
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 23 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Expand Up @@ -80,6 +80,9 @@ To be released.
- Added `Block<T>.Deserialize(byte[])` method. [[#751]]
- Added `Transaction<T>.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

Expand Down Expand Up @@ -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
Expand Down
19 changes: 19 additions & 0 deletions Libplanet/Crypto/CryptoConfig.cs
@@ -0,0 +1,19 @@
namespace Libplanet.Crypto
{
/// <summary>
/// Libplanet cryptography configuration information.
/// </summary>
public static class CryptoConfig
{
private static ICryptoBackend _cryptoBackend;

/// <summary>
/// Global cryptography backend to sign and verify messages.
/// </summary>
public static ICryptoBackend CryptoBackend
{
get => _cryptoBackend ?? (_cryptoBackend = new DefaultCryptoBackend());
set => _cryptoBackend = value;
}
}
}
34 changes: 34 additions & 0 deletions 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;
}
}
}
}
24 changes: 24 additions & 0 deletions Libplanet/Crypto/ICryptoBackend.cs
@@ -0,0 +1,24 @@
namespace Libplanet.Crypto
{
/// <summary>
/// Cryptography backend interface.
/// </summary>
public interface ICryptoBackend
{
/// <summary>
/// Verifies whether a <paramref name="signature"/> was created from
/// a <paramref name="messageHash"/> with the corresponding <see cref="PrivateKey"/>.
/// </summary>
/// <param name="messageHash">A 32 bytes message hash digest hashed with SHA256.</param>
/// <param name="signature">A signature that was created from the
/// <paramref name="messageHash"/>.</param>
/// <param name="publicKey"><see cref="PublicKey"/> used for verification.</param>
/// <returns><c>true</c> if the <paramref name="signature"/> was created
/// from the <paramref name="messageHash"/> with the corresponding
/// <see cref="PrivateKey"/>. Otherwise <c>false</c>.</returns>
bool Verify(
byte[] messageHash,
byte[] signature,
PublicKey publicKey);
}
}
41 changes: 18 additions & 23 deletions 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
{
Expand Down Expand Up @@ -112,23 +111,7 @@ public byte[] Encrypt(byte[] message)
/// from the <paramref name="message"/> with the corresponding
/// <see cref="PrivateKey"/>. Otherwise <c>false</c>.</returns>
[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)
{
Expand All @@ -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
);
}
}
}

0 comments on commit 0968c79

Please sign in to comment.