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

RC3 to RC4 Comparison #9

Open
wants to merge 17 commits into
base: rc3-untouched
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
51 changes: 38 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,43 @@ 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 = new Org.BouncyCastle.Crypto.Signers.ECDsaSigner();
signer.Init(false, pubKey);

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);

return signer.VerifySignature(message.Sha256(), r, s);
}
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
2 changes: 1 addition & 1 deletion src/neo/Cryptography/ECC/ECCurve.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class ECCurve
internal readonly BigInteger Q;
internal readonly ECFieldElement A;
internal readonly ECFieldElement B;
internal readonly BigInteger N;
public readonly BigInteger N;
/// <summary>
/// The point at infinity.
/// </summary>
Expand Down
14 changes: 13 additions & 1 deletion src/neo/Cryptography/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,22 @@ public static byte[] RIPEMD160(this ReadOnlySpan<byte> value)
/// <returns>The computed hash code.</returns>
public static uint Murmur32(this byte[] value, uint seed)
{
using Murmur3 murmur = new(seed);
using Murmur32 murmur = new(seed);
return BinaryPrimitives.ReadUInt32LittleEndian(murmur.ComputeHash(value));
}

/// <summary>
/// Computes the 128-bit hash value for the specified byte array using the murmur algorithm.
/// </summary>
/// <param name="value">The input to compute the hash code for.</param>
/// <param name="seed">The seed used by the murmur algorithm.</param>
/// <returns>The computed hash code.</returns>
public static byte[] Murmur128(this byte[] value, uint seed)
{
using Murmur128 murmur = new(seed);
return murmur.ComputeHash(value);
}

/// <summary>
/// Computes the hash value for the specified byte array using the sha256 algorithm.
/// </summary>
Expand Down
131 changes: 131 additions & 0 deletions src/neo/Cryptography/Murmur128.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
using System;
using System.Buffers.Binary;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;

namespace Neo.Cryptography
{
/// <summary>
/// Computes the 128 bits murmur hash for the input data.
/// </summary>
public sealed class Murmur128 : HashAlgorithm
{
private const ulong c1 = 0x87c37b91114253d5;
private const ulong c2 = 0x4cf5ad432745937f;
private const int r1 = 31;
private const int r2 = 33;
private const uint m = 5;
private const uint n1 = 0x52dce729;
private const uint n2 = 0x38495ab5;

private readonly uint seed;
private int length;

public override int HashSize => 128;

private ulong H1 { get; set; }
private ulong H2 { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="Murmur128"/> class with the specified seed.
/// </summary>
/// <param name="seed">The seed to be used.</param>
public Murmur128(uint seed)
{
this.seed = seed;
Initialize();
}

protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
length += cbSize;
int remainder = cbSize & 15;
int alignedLength = ibStart + (cbSize - remainder);
for (int i = ibStart; i < alignedLength; i += 16)
{
ulong k1 = BinaryPrimitives.ReadUInt64LittleEndian(array.AsSpan(i));
k1 *= c1;
k1 = BitOperations.RotateLeft(k1, r1);
k1 *= c2;
H1 ^= k1;
H1 = BitOperations.RotateLeft(H1, 27);
H1 += H2;
H1 = H1 * m + n1;

ulong k2 = BinaryPrimitives.ReadUInt64LittleEndian(array.AsSpan(i + 8));
k2 *= c2;
k2 = BitOperations.RotateLeft(k2, r2);
k2 *= c1;
H2 ^= k2;
H2 = BitOperations.RotateLeft(H2, 31);
H2 += H1;
H2 = H2 * m + n2;
}

if (remainder > 0)
{
ulong remainingBytesL = 0, remainingBytesH = 0;
switch (remainder)
{
case 15: remainingBytesH ^= (ulong)array[alignedLength + 14] << 48; goto case 14;
case 14: remainingBytesH ^= (ulong)array[alignedLength + 13] << 40; goto case 13;
case 13: remainingBytesH ^= (ulong)array[alignedLength + 12] << 32; goto case 12;
case 12: remainingBytesH ^= (ulong)array[alignedLength + 11] << 24; goto case 11;
case 11: remainingBytesH ^= (ulong)array[alignedLength + 10] << 16; goto case 10;
case 10: remainingBytesH ^= (ulong)array[alignedLength + 9] << 8; goto case 9;
case 9: remainingBytesH ^= (ulong)array[alignedLength + 8] << 0; goto case 8;
case 8: remainingBytesL ^= (ulong)array[alignedLength + 7] << 56; goto case 7;
case 7: remainingBytesL ^= (ulong)array[alignedLength + 6] << 48; goto case 6;
case 6: remainingBytesL ^= (ulong)array[alignedLength + 5] << 40; goto case 5;
case 5: remainingBytesL ^= (ulong)array[alignedLength + 4] << 32; goto case 4;
case 4: remainingBytesL ^= (ulong)array[alignedLength + 3] << 24; goto case 3;
case 3: remainingBytesL ^= (ulong)array[alignedLength + 2] << 16; goto case 2;
case 2: remainingBytesL ^= (ulong)array[alignedLength + 1] << 8; goto case 1;
case 1: remainingBytesL ^= (ulong)array[alignedLength] << 0; break;
}

H2 ^= BitOperations.RotateLeft(remainingBytesH * c2, r2) * c1;
H1 ^= BitOperations.RotateLeft(remainingBytesL * c1, r1) * c2;
}
}

protected override byte[] HashFinal()
{
ulong len = (ulong)length;
H1 ^= len; H2 ^= len;

H1 += H2;
H2 += H1;

H1 = FMix(H1);
H2 = FMix(H2);

H1 += H2;
H2 += H1;

var buffer = new byte[sizeof(ulong) * 2];
Span<byte> bytes = buffer;

BinaryPrimitives.WriteUInt64LittleEndian(bytes, H1);
BinaryPrimitives.WriteUInt64LittleEndian(bytes[sizeof(ulong)..], H2);

return buffer;
}

public override void Initialize()
{
H1 = H2 = seed;
length = 0;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong FMix(ulong h)
{
h = (h ^ (h >> 33)) * 0xff51afd7ed558ccd;
h = (h ^ (h >> 33)) * 0xc4ceb9fe1a85ec53;

return (h ^ (h >> 33));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
using System;
using System.Buffers.Binary;
using System.Runtime.CompilerServices;
using System.Numerics;
using System.Security.Cryptography;

namespace Neo.Cryptography
{
/// <summary>
/// Computes the murmur hash for the input data.
/// </summary>
public sealed class Murmur3 : HashAlgorithm
public sealed class Murmur32 : HashAlgorithm
{
private const uint c1 = 0xcc9e2d51;
private const uint c2 = 0x1b873593;
Expand All @@ -24,10 +24,10 @@ public sealed class Murmur3 : HashAlgorithm
public override int HashSize => 32;

/// <summary>
/// Initializes a new instance of the <see cref="Murmur3"/> class with the specified seed.
/// Initializes a new instance of the <see cref="Murmur32"/> class with the specified seed.
/// </summary>
/// <param name="seed">The seed to be used.</param>
public Murmur3(uint seed)
public Murmur32(uint seed)
{
this.seed = seed;
Initialize();
Expand All @@ -42,10 +42,10 @@ protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
uint k = BinaryPrimitives.ReadUInt32LittleEndian(array.AsSpan(i));
k *= c1;
k = RotateLeft(k, r1);
k = BitOperations.RotateLeft(k, r1);
k *= c2;
hash ^= k;
hash = RotateLeft(hash, r2);
hash = BitOperations.RotateLeft(hash, r2);
hash = hash * m + n;
}
if (remainder > 0)
Expand All @@ -58,7 +58,7 @@ protected override void HashCore(byte[] array, int ibStart, int cbSize)
case 1: remainingBytes ^= array[alignedLength]; break;
}
remainingBytes *= c1;
remainingBytes = RotateLeft(remainingBytes, r1);
remainingBytes = BitOperations.RotateLeft(remainingBytes, r1);
remainingBytes *= c2;
hash ^= remainingBytes;
}
Expand All @@ -83,11 +83,5 @@ public override void Initialize()
hash = seed;
length = 0;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint RotateLeft(uint x, byte n)
{
return (x << n) | (x >> (32 - n));
}
}
}
4 changes: 2 additions & 2 deletions src/neo/IO/Json/JPathToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ private static void ProcessRecursiveDescent(ref JObject[] objects, ref int maxDe
if (token.Type != JPathTokenType.Identifier) throw new FormatException();
while (objects.Length > 0)
{
results.AddRange(objects.SelectMany(p => p.Properties).Where(p => p.Key == token.Content).Select(p => p.Value));
results.AddRange(objects.Where(p => p is not null).SelectMany(p => p.Properties).Where(p => p.Key == token.Content).Select(p => p.Value));
Descent(ref objects, ref maxDepth);
}
objects = results.ToArray();
Expand Down Expand Up @@ -259,7 +259,7 @@ private static void Descent(ref JObject[] objects, ref int maxDepth)
{
if (maxDepth <= 0) throw new InvalidOperationException();
--maxDepth;
objects = objects.SelectMany(p => p is JArray array ? array : p.Properties.Values).ToArray();
objects = objects.Where(p => p is not null).SelectMany(p => p is JArray array ? array : p.Properties.Values).ToArray();
}

private static void Descent(ref JObject[] objects, ref int maxDepth, params string[] names)
Expand Down
1 change: 1 addition & 0 deletions src/neo/NeoSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ public NeoSystem(ProtocolSettings settings, string storageEngine = null, string
PrevHash = UInt256.Zero,
MerkleRoot = UInt256.Zero,
Timestamp = (new DateTime(2016, 7, 15, 15, 8, 21, DateTimeKind.Utc)).ToTimestampMS(),
Nonce = 2083236893, // nonce from the Bitcoin genesis block.
Index = 0,
PrimaryIndex = 0,
NextConsensus = Contract.GetBFTAddress(settings.StandbyValidators),
Expand Down
5 changes: 5 additions & 0 deletions src/neo/Network/P2P/Payloads/Block.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ public sealed class Block : IEquatable<Block>, IInventory
/// </summary>
public ulong Timestamp => Header.Timestamp;

/// <summary>
/// The random number of the block.
/// </summary>
public ulong Nonce => Header.Nonce;

/// <summary>
/// The index of the block.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/neo/Network/P2P/Payloads/ExtensiblePayload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ internal bool Verify(ProtocolSettings settings, DataCache snapshot, ISet<UInt160
uint height = NativeContract.Ledger.CurrentIndex(snapshot);
if (height < ValidBlockStart || height >= ValidBlockEnd) return false;
if (!extensibleWitnessWhiteList.Contains(Sender)) return false;
return this.VerifyWitnesses(settings, snapshot, 0_02000000);
return this.VerifyWitnesses(settings, snapshot, 0_06000000L);
}
}
}
Loading