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

[neox-2.x] add interop services #1597

Merged
merged 21 commits into from
May 6, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions neo.UnitTests/UT_ECDsa.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Security.Cryptography;
using System.Numerics;

namespace Neo.Cryptography.ECC.Tests
{
[TestClass()]
public class UT_ECDsa
{
private ECDsa ecdsa;

ZhangTao1596 marked this conversation as resolved.
Show resolved Hide resolved
public static byte[] generatekey(int privateKeyLength)
{
byte[] privateKey = new byte[privateKeyLength];
using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
{
rng.GetBytes(privateKey);
}
return privateKey;
}

[TestMethod()]
public void KeyRecoverTest()
{
byte[] privateKey = generatekey(32);
ECPoint publickey = ECCurve.Secp256k1.G * privateKey;
ecdsa = new ECDsa(privateKey, ECCurve.Secp256k1);
byte[] message = System.Text.Encoding.Default.GetBytes("HelloWorld");
BigInteger[] signatures = ecdsa.GenerateSignature(message);
BigInteger r = signatures[0];
BigInteger s = signatures[1];
bool v;
if (signatures[2] == 0)
{
v = true;
}
else
{
v = false;
}
ECPoint recoverKey = ECDsa.KeyRecover(ECCurve.Secp256k1, r, s, message, v, true);
Assert.IsTrue(recoverKey.Equals(publickey));
//wrong key part
r = new System.Numerics.BigInteger(generatekey(32));
try
{
recoverKey = ECDsa.KeyRecover(ECCurve.Secp256k1, r, signatures[1], message, true, true);
Assert.IsFalse(recoverKey.Equals(publickey));
shargon marked this conversation as resolved.
Show resolved Hide resolved
}
//wrong key may cause exception in decompresspoint
catch { }
s = new System.Numerics.BigInteger(generatekey(32));
try
{
recoverKey = ECDsa.KeyRecover(ECCurve.Secp256k1, signatures[0], s, message, true, true);
Assert.IsFalse(recoverKey.Equals(publickey));
}
//wrong key may cause exception in decompresspoint
catch { }
}
}
}
15 changes: 14 additions & 1 deletion neo.UnitTests/UT_Helper.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
using FluentAssertions;
using System.Numerics;
ZhangTao1596 marked this conversation as resolved.
Show resolved Hide resolved
using System.Globalization;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo.Network.P2P;
using Neo.SmartContract;
using Neo.Cryptography;
using Neo.Wallets;
using Neo.Cryptography.ECC;

namespace Neo.UnitTests
{
Expand Down Expand Up @@ -38,5 +42,14 @@ public void ToScriptHash()
res.Should().Be(UInt160.Parse("2d3b96ae1bcc5a585e075e3b81920210dec16302"));
}

[TestMethod()]
public void Keccak256Test()
{
byte[] messageA = System.Text.Encoding.Default.GetBytes("HelloWorld");
byte[] messageB = System.Text.Encoding.Default.GetBytes("HiWorld");
Assert.IsFalse(messageA.Keccak256().Equals(messageB.Keccak256()));
Assert.IsTrue(messageA.Keccak256().Length == 32 && messageB.Keccak256().Length == 32);
ZhangTao1596 marked this conversation as resolved.
Show resolved Hide resolved
Assert.IsTrue(messageA.Keccak256().ToHexString() == "7c5ea36004851c764c44143b1dcb59679b11c9a68e5f41497f6cf3d480715331");
}
}
}
52 changes: 50 additions & 2 deletions neo/Cryptography/ECC/ECDsa.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public BigInteger[] GenerateSignature(byte[] message)
if (privateKey == null) throw new InvalidOperationException();
BigInteger e = CalculateE(curve.N, message);
BigInteger d = new BigInteger(privateKey.Reverse().Concat(new byte[1]).ToArray());
BigInteger r, s;
BigInteger r, s, id;
ZhangTao1596 marked this conversation as resolved.
Show resolved Hide resolved
using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
{
do
Expand All @@ -53,6 +53,7 @@ public BigInteger[] GenerateSignature(byte[] message)
}
while (k.Sign == 0 || k.CompareTo(curve.N) >= 0);
ECPoint p = ECPoint.Multiply(curve.G, k);
id = p.Y.Value & 1;
BigInteger x = p.X.Value;
r = x.Mod(curve.N);
}
Expand All @@ -61,11 +62,12 @@ public BigInteger[] GenerateSignature(byte[] message)
if (s > curve.N / 2)
{
s = curve.N - s;
id = id ^ 1;
}
}
while (s.Sign == 0);
}
return new BigInteger[] { r, s };
return new BigInteger[] { r, s, id };
}

private static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger k, ECPoint Q, BigInteger l)
Expand Down Expand Up @@ -104,5 +106,51 @@ public bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
BigInteger v = point.X.Value.Mod(curve.N);
return v.Equals(r);
}

public static ECPoint KeyRecover(ECCurve curve, BigInteger r, BigInteger s, byte[] msg, bool IsEven, bool doChecks)
ZhangTao1596 marked this conversation as resolved.
Show resolved Hide resolved
{
shargon marked this conversation as resolved.
Show resolved Hide resolved
// calculate h
BigInteger h = (curve.Q + 1 + 2 * (BigInteger)Math.Sqrt((double)curve.Q)) / curve.N;
BigInteger e;
ECPoint Q = new ECPoint();
int messageBitLength;

for (int j = 0; j <= h; j++)
ZhangTao1596 marked this conversation as resolved.
Show resolved Hide resolved
{
// step 1.1 x = (n * i) + r
BigInteger Rx = curve.N * j + r;
if (Rx > curve.Q) break;

// step 1.2 and 1.3 get point R
ECPoint R;
if (IsEven)
{
R = ECPoint.DecompressPoint(0, Rx, curve);
}
else
{
R = ECPoint.DecompressPoint(1, Rx, curve);
}
if (doChecks)
ZhangTao1596 marked this conversation as resolved.
Show resolved Hide resolved
{
if (ECPoint.Multiply(R, curve.N) != curve.Infinity)
continue;
}

// step 1.5 compute e
messageBitLength = msg.Length * 8;
e = new BigInteger(msg.Reverse().Concat(new byte[1]).ToArray());
if (curve.N.GetBitLength() < messageBitLength)
{
e >>= messageBitLength - curve.N.GetBitLength();
}

// step 1.6 Q = r^-1 (sR-eG)
BigInteger invr = r.ModInverse(curve.N);
ECPoint t0 = ECPoint.Multiply(R, s) - ECPoint.Multiply(curve.G, e);
Q = ECPoint.Multiply(t0, invr);
}
return Q;
}
}
}
2 changes: 1 addition & 1 deletion neo/Cryptography/ECC/ECPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public static ECPoint DecodePoint(byte[] encoded, ECCurve curve)
return p;
}

private static ECPoint DecompressPoint(int yTilde, BigInteger X1, ECCurve curve)
public static ECPoint DecompressPoint(int yTilde, BigInteger X1, ECCurve curve)
{
ECFieldElement x = new ECFieldElement(X1, curve);
ECFieldElement alpha = x * (x.Square() + curve.A) + curve.B;
Expand Down
10 changes: 10 additions & 0 deletions neo/Cryptography/Helper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Neo.IO;
using Neo.Network.P2P.Payloads;
using Org.BouncyCastle.Crypto.Digests;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -91,6 +92,15 @@ public static string Base58CheckEncode(this byte[] data)
return Base58.Encode(buffer);
}

public static byte[] Keccak256(this byte[] value)
{
var digest = new KeccakDigest(256);
byte[] hash = new byte[digest.GetDigestSize()];
digest.BlockUpdate(value, 0, value.Length);
digest.DoFinal(hash, 0);
return hash;
}

public static byte[] RIPEMD160(this IEnumerable<byte> value)
{
return _ripemd160.Value.ComputeHash(value.ToArray());
Expand Down
36 changes: 35 additions & 1 deletion neo/SmartContract/NeoService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using Neo.Cryptography.ECC;
using Neo.Cryptography;
using Neo.Cryptography.ECC;
using Neo.Ledger;
using Neo.Network.P2P;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.SmartContract.Enumerators;
Expand Down Expand Up @@ -99,6 +101,8 @@ public NeoService(TriggerType trigger, Snapshot snapshot)
Register("Neo.Iterator.Keys", Iterator_Keys, 1);
Register("Neo.Iterator.Values", Iterator_Values, 1);
Register("Neo.Iterator.Concat", Iterator_Concat, 1);
Register("Neo.Cryptography.Keccak256", Keccak256, 1);
ZhangTao1596 marked this conversation as resolved.
Show resolved Hide resolved
Register("Neo.Cryptography.Ecrecover", Ecrecover, 1);

#region Aliases
Register("Neo.Iterator.Next", Enumerator_Next, 1);
Expand Down Expand Up @@ -165,6 +169,36 @@ public NeoService(TriggerType trigger, Snapshot snapshot)
#endregion
}

/// <summary>
///
ZhangTao1596 marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
/// <param name="engine">r, s, v, messageHash</param>
/// <returns></returns>
private bool Ecrecover(ExecutionEngine engine)
{
var r = new System.Numerics.BigInteger(engine.CurrentContext.EvaluationStack.Pop().GetByteArray().Reverse().Concat(new byte[1]).ToArray());
shargon marked this conversation as resolved.
Show resolved Hide resolved
var s = new System.Numerics.BigInteger(engine.CurrentContext.EvaluationStack.Pop().GetByteArray().Reverse().Concat(new byte[1]).ToArray());
bool v = engine.CurrentContext.EvaluationStack.Pop().GetBoolean();
byte[] messageHash = engine.CurrentContext.EvaluationStack.Pop().GetByteArray();
try
{
ECPoint point = ECDsa.KeyRecover(ECCurve.Secp256k1, r, s, messageHash, v, true);
ZhangTao1596 marked this conversation as resolved.
Show resolved Hide resolved
engine.CurrentContext.EvaluationStack.Push(point.EncodePoint(false).Skip(1).ToArray());
}
catch
{
engine.CurrentContext.EvaluationStack.Push(new byte[] { 0x00 });
ZhangTao1596 marked this conversation as resolved.
Show resolved Hide resolved
}
return true;
}

private bool Keccak256(ExecutionEngine engine)
{
var message = engine.CurrentContext.EvaluationStack.Pop().GetByteArray();
engine.CurrentContext.EvaluationStack.Push(message.Keccak256());
return true;
}

private bool Blockchain_GetAccount(ExecutionEngine engine)
{
UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());
Expand Down
3 changes: 2 additions & 1 deletion neo/SmartContract/StandardService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Neo.Cryptography.ECC;
using Neo.Cryptography;
using Neo.Cryptography.ECC;
using Neo.IO;
using Neo.Ledger;
using Neo.Network.P2P.Payloads;
Expand Down
1 change: 1 addition & 0 deletions neo/neo.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

<ItemGroup>
<PackageReference Include="Akka" Version="1.3.11" />
<PackageReference Include="BouncyCastle.NetCore" Version="1.8.5" />
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.2.0" />
Expand Down