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
56 changes: 44 additions & 12 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,50 @@ 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.Secp256r1)
{
Curve = curve,
Q = new ECPoint
try
{
X = buffer[1..33],
Y = buffer[33..]
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);
}
});
return ecdsa.VerifyData(message, signature, HashAlgorithmName.SHA256);
catch { return false; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this try-catch?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ZhangTao1596 could you test it without the try block in osx?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ZhangTao1596 could you test it without the try block in osx?

I think it's OK since we already went into 'try', but we can't go to 'catch'. After remove, no effect on the result.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I still suggest keeping the try-catch for a THIRD-PARTY lib, unless you know it very well.

}
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
{
Curve = curve,
Q = new ECPoint
{
X = buffer[1..33],
Y = buffer[33..]
}
});
return ecdsa.VerifyData(message, signature, HashAlgorithmName.SHA256);
}
}

/// <summary>
Expand Down