Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OSX compatible #2511

Merged
merged 15 commits into from
Jul 16, 2021
54 changes: 41 additions & 13 deletions src/neo/Cryptography/Crypto.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;

namespace Neo.Cryptography
Expand All @@ -8,6 +9,8 @@ namespace Neo.Cryptography
/// </summary>
public static class Crypto
{
private static readonly bool IsOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);

/// <summary>
/// Calculates the 160-bit hash value of the specified message.
/// </summary>
Expand Down Expand Up @@ -59,21 +62,46 @@ public static byte[] Sign(byte[] message, byte[] prikey, byte[] pubkey)
/// <returns><see langword="true"/> if the signature is valid; otherwise, <see langword="false"/>.</returns>
public static bool VerifySignature(ReadOnlySpan<byte> message, ReadOnlySpan<byte> signature, ECC.ECPoint pubkey)
{
ECCurve curve =
pubkey.Curve == ECC.ECCurve.Secp256r1 ? ECCurve.NamedCurves.nistP256 :
pubkey.Curve == ECC.ECCurve.Secp256k1 ? ECCurve.CreateFromFriendlyName("secP256k1") :
throw new NotSupportedException();
byte[] buffer = pubkey.EncodePoint(false);
using var ecdsa = ECDsa.Create(new ECParameters
if (signature.Length != 64) return false;

if (IsOSX && pubkey.Curve == ECC.ECCurve.Secp256k1)
{
Curve = curve,
Q = new ECPoint
var curve = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1");
var domain = new Org.BouncyCastle.Crypto.Parameters.ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
var point = curve.Curve.CreatePoint(
new Org.BouncyCastle.Math.BigInteger(pubkey.X.Value.ToString()),
new Org.BouncyCastle.Math.BigInteger(pubkey.Y.Value.ToString()));
var pubKey = new Org.BouncyCastle.Crypto.Parameters.ECPublicKeyParameters("ECDSA", point, domain);
var signer = Org.BouncyCastle.Security.SignerUtilities.GetSigner("SHA-256withECDSA");

signer.Init(false, pubKey);
signer.BlockUpdate(message.ToArray(), 0, message.Length);

var sig = signature.ToArray();
var r = new Org.BouncyCastle.Math.BigInteger(1, sig, 0, 32);
var s = new Org.BouncyCastle.Math.BigInteger(1, sig, 32, 32);
sig = new Org.BouncyCastle.Asn1.DerSequence(new Org.BouncyCastle.Asn1.DerInteger(r), new Org.BouncyCastle.Asn1.DerInteger(s)).GetDerEncoded();

return signer.VerifySignature(sig);
}
else
{
ECCurve curve =
pubkey.Curve == ECC.ECCurve.Secp256r1 ? ECCurve.NamedCurves.nistP256 :
pubkey.Curve == ECC.ECCurve.Secp256k1 ? ECCurve.CreateFromFriendlyName("secP256k1") :
throw new NotSupportedException();
byte[] buffer = pubkey.EncodePoint(false);
using var ecdsa = ECDsa.Create(new ECParameters
{
X = buffer[1..33],
Y = buffer[33..]
}
});
return ecdsa.VerifyData(message, signature, HashAlgorithmName.SHA256);
Curve = curve,
Q = new ECPoint
{
X = buffer[1..33],
Y = buffer[33..]
}
});
return ecdsa.VerifyData(message, signature, HashAlgorithmName.SHA256);
}
}

/// <summary>
Expand Down