From 0be3125756392c58af25a47f7ba80ccaf312415b Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Tue, 26 Nov 2019 11:34:58 +0800 Subject: [PATCH] Optimize BigInteger (#1280) --- src/neo/Cryptography/Base58.cs | 7 +++---- src/neo/Cryptography/ECC/ECDsa.cs | 5 ++--- src/neo/Cryptography/ECC/ECFieldElement.cs | 8 +++----- src/neo/Cryptography/ECC/ECPoint.cs | 12 ++++++------ 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/neo/Cryptography/Base58.cs b/src/neo/Cryptography/Base58.cs index 9ddbea3dc8..1920bed10d 100644 --- a/src/neo/Cryptography/Base58.cs +++ b/src/neo/Cryptography/Base58.cs @@ -25,16 +25,15 @@ public static byte[] Decode(string input) // Leading zero bytes get encoded as leading `1` characters int leadingZeroCount = input.TakeWhile(c => c == Alphabet[0]).Count(); var leadingZeros = new byte[leadingZeroCount]; - var bytesWithoutLeadingZeros = bi.ToByteArray() - .Reverse()// to big endian - .SkipWhile(b => b == 0);//strip sign byte + if (bi.IsZero) return leadingZeros; + var bytesWithoutLeadingZeros = bi.ToByteArray(isUnsigned: true, isBigEndian: true); return leadingZeros.Concat(bytesWithoutLeadingZeros).ToArray(); } public static string Encode(byte[] input) { // Decode byte[] to BigInteger - BigInteger value = new BigInteger(new byte[1].Concat(input).Reverse().ToArray()); + BigInteger value = new BigInteger(input, isUnsigned: true, isBigEndian: true); // Encode BigInteger to Base58 string var sb = new StringBuilder(); diff --git a/src/neo/Cryptography/ECC/ECDsa.cs b/src/neo/Cryptography/ECC/ECDsa.cs index 07373a7844..cae8dc4e7c 100644 --- a/src/neo/Cryptography/ECC/ECDsa.cs +++ b/src/neo/Cryptography/ECC/ECDsa.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Numerics; using System.Security.Cryptography; @@ -26,7 +25,7 @@ public ECDsa(ECPoint publicKey) private BigInteger CalculateE(BigInteger n, byte[] message) { int messageBitLength = message.Length * 8; - BigInteger trunc = new BigInteger(message.Reverse().Concat(new byte[1]).ToArray()); + BigInteger trunc = new BigInteger(message, isUnsigned: true, isBigEndian: true); if (n.GetBitLength() < messageBitLength) { trunc >>= messageBitLength - n.GetBitLength(); @@ -38,7 +37,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 d = new BigInteger(privateKey, isUnsigned: true, isBigEndian: true); BigInteger r, s; using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) { diff --git a/src/neo/Cryptography/ECC/ECFieldElement.cs b/src/neo/Cryptography/ECC/ECFieldElement.cs index 331e1e4408..33d593b4cf 100644 --- a/src/neo/Cryptography/ECC/ECFieldElement.cs +++ b/src/neo/Cryptography/ECC/ECFieldElement.cs @@ -142,12 +142,10 @@ public ECFieldElement Square() public byte[] ToByteArray() { - byte[] data = Value.ToByteArray(); + byte[] data = Value.ToByteArray(isUnsigned: true, isBigEndian: true); if (data.Length == 32) - return data.Reverse().ToArray(); - if (data.Length > 32) - return data.Take(32).Reverse().ToArray(); - return Enumerable.Repeat(0, 32 - data.Length).Concat(data.Reverse()).ToArray(); + return data; + return Enumerable.Repeat(0, 32 - data.Length).Concat(data).ToArray(); } public static ECFieldElement operator -(ECFieldElement x) diff --git a/src/neo/Cryptography/ECC/ECPoint.cs b/src/neo/Cryptography/ECC/ECPoint.cs index 803aab9987..d597c4a8c5 100644 --- a/src/neo/Cryptography/ECC/ECPoint.cs +++ b/src/neo/Cryptography/ECC/ECPoint.cs @@ -52,7 +52,7 @@ public static ECPoint DecodePoint(byte[] encoded, ECCurve curve) if (encoded.Length != (expectedLength + 1)) throw new FormatException("Incorrect length for compressed encoding"); int yTilde = encoded[0] & 1; - BigInteger X1 = new BigInteger(encoded.Skip(1).Reverse().Concat(new byte[1]).ToArray()); + BigInteger X1 = new BigInteger(encoded.AsSpan(1), isUnsigned: true, isBigEndian: true); p = DecompressPoint(yTilde, X1, curve); break; } @@ -60,8 +60,8 @@ public static ECPoint DecodePoint(byte[] encoded, ECCurve curve) { if (encoded.Length != (2 * expectedLength + 1)) throw new FormatException("Incorrect length for uncompressed/hybrid encoding"); - BigInteger X1 = new BigInteger(encoded.Skip(1).Take(expectedLength).Reverse().Concat(new byte[1]).ToArray()); - BigInteger Y1 = new BigInteger(encoded.Skip(1 + expectedLength).Reverse().Concat(new byte[1]).ToArray()); + BigInteger X1 = new BigInteger(encoded.AsSpan(1, expectedLength), isUnsigned: true, isBigEndian: true); + BigInteger Y1 = new BigInteger(encoded.AsSpan(1 + expectedLength), isUnsigned: true, isBigEndian: true); p = new ECPoint(new ECFieldElement(X1, curve), new ECFieldElement(Y1, curve), curve); break; } @@ -143,10 +143,10 @@ public byte[] EncodePoint(bool commpressed) else { data = new byte[65]; - byte[] yBytes = Y.Value.ToByteArray().Reverse().ToArray(); + byte[] yBytes = Y.Value.ToByteArray(isUnsigned: true, isBigEndian: true); Buffer.BlockCopy(yBytes, 0, data, 65 - yBytes.Length, yBytes.Length); } - byte[] xBytes = X.Value.ToByteArray().Reverse().ToArray(); + byte[] xBytes = X.Value.ToByteArray(isUnsigned: true, isBigEndian: true); Buffer.BlockCopy(xBytes, 0, data, 33 - xBytes.Length, xBytes.Length); data[0] = commpressed ? Y.Value.IsEven ? (byte)0x02 : (byte)0x03 : (byte)0x04; return data; @@ -379,7 +379,7 @@ private static sbyte[] WindowNaf(sbyte width, BigInteger k) throw new ArgumentException(); if (p.IsInfinity) return p; - BigInteger k = new BigInteger(n.Reverse().Concat(new byte[1]).ToArray()); + BigInteger k = new BigInteger(n, isUnsigned: true, isBigEndian: true); if (k.Sign == 0) return p.Curve.Infinity; return Multiply(p, k);