diff --git a/crypto/src/math/BigInteger.cs b/crypto/src/math/BigInteger.cs
index d84680de5..7da886c4f 100644
--- a/crypto/src/math/BigInteger.cs
+++ b/crypto/src/math/BigInteger.cs
@@ -475,8 +475,15 @@ namespace Org.BouncyCastle.Math
}
public BigInteger(byte[] bytes)
- : this(bytes, 0, bytes.Length)
{
+ this.magnitude = InitBE(bytes, 0, bytes.Length, out this.sign);
+ }
+
+ public BigInteger(byte[] bytes, bool bigEndian)
+ {
+ this.magnitude = bigEndian
+ ? InitBE(bytes, 0, bytes.Length, out this.sign)
+ : InitLE(bytes, 0, bytes.Length, out this.sign);
}
public BigInteger(byte[] bytes, int offset, int length)
@@ -484,16 +491,30 @@ namespace Org.BouncyCastle.Math
if (length == 0)
throw new FormatException("Zero length BigInteger");
- // TODO Move this processing into MakeMagnitude (provide sign argument)
+ this.magnitude = InitBE(bytes, offset, length, out this.sign);
+ }
+
+ public BigInteger(byte[] bytes, int offset, int length, bool bigEndian)
+ {
+ if (length <= 0)
+ throw new FormatException("Zero length BigInteger");
+
+ this.magnitude = bigEndian
+ ? InitBE(bytes, offset, length, out this.sign)
+ : InitLE(bytes, offset, length, out this.sign);
+ }
+
+ private static uint[] InitBE(byte[] bytes, int offset, int length, out int sign)
+ {
+ // TODO Move this processing into MakeMagnitudeBE (provide sign argument)
if ((sbyte)bytes[offset] >= 0)
{
- // strip leading zero bytes and return magnitude bytes
- this.magnitude = MakeMagnitude(bytes, offset, length);
- this.sign = this.magnitude.Length > 0 ? 1 : 0;
- return;
+ uint[] magnitude = MakeMagnitudeBE(bytes, offset, length);
+ sign = magnitude.Length > 0 ? 1 : 0;
+ return magnitude;
}
- this.sign = -1;
+ sign = -1;
int end = offset + length;
@@ -504,10 +525,7 @@ namespace Org.BouncyCastle.Math
}
if (iBval >= end)
- {
- this.magnitude = One.magnitude;
- return;
- }
+ return One.magnitude;
int numBytes = end - iBval;
@@ -534,124 +552,210 @@ namespace Org.BouncyCastle.Math
inverse[index]++;
- this.magnitude = MakeMagnitude(inverse);
- }
-
- private static uint[] MakeMagnitude(byte[] bytes)
- {
- return MakeMagnitude(bytes, 0, bytes.Length);
+ return MakeMagnitudeBE(inverse);
}
- private static uint[] MakeMagnitude(byte[] bytes, int offset, int length)
+ private static uint[] InitLE(byte[] bytes, int offset, int length, out int sign)
{
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- return MakeMagnitude(bytes.AsSpan(offset, length));
-#else
int end = offset + length;
- // strip leading zeros
- int firstSignificant;
- for (firstSignificant = offset; firstSignificant < end && bytes[firstSignificant] == 0; firstSignificant++)
+ // TODO Move this processing into MakeMagnitudeLE (provide sign argument)
+ if ((sbyte)bytes[end - 1] >= 0)
{
+ uint[] magnitude = MakeMagnitudeLE(bytes, offset, length);
+ sign = magnitude.Length > 0 ? 1 : 0;
+ return magnitude;
}
- if (firstSignificant >= end)
- return ZeroMagnitude;
+ sign = -1;
- int nInts = (end - firstSignificant + 3) / BytesPerInt;
- int bCount = (end - firstSignificant) % BytesPerInt;
- if (bCount == 0)
+ // strip leading sign bytes
+ int last = length;
+ while (--last >= 0 && bytes[offset + last] == byte.MaxValue)
{
- bCount = BytesPerInt;
}
- if (nInts < 1)
- return ZeroMagnitude;
+ if (last < 0)
+ return One.magnitude;
- uint[] mag = new uint[nInts];
+ int numBytes = last + 1;
- uint v = 0U;
- int magnitudeIndex = 0;
- for (int i = firstSignificant; i < end; ++i)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ Span<byte> inverse = numBytes <= 512
+ ? stackalloc byte[numBytes]
+ : new byte[numBytes];
+#else
+ byte[] inverse = new byte[numBytes];
+#endif
+
+ for (int i = 0; i < numBytes; ++i)
{
- v <<= 8;
- v |= bytes[i];
- bCount--;
- if (bCount <= 0)
- {
- mag[magnitudeIndex] = v;
- magnitudeIndex++;
- bCount = BytesPerInt;
- v = 0U;
- }
+ inverse[i] = (byte)~bytes[offset + i];
+ }
+
+ int index = 0;
+ while (inverse[index] == byte.MaxValue)
+ {
+ inverse[index++] = byte.MinValue;
}
- if (magnitudeIndex < mag.Length)
+ inverse[index]++;
+
+ return MakeMagnitudeLE(inverse);
+ }
+
+ private static uint[] MakeMagnitudeBE(byte[] bytes)
+ {
+ return MakeMagnitudeBE(bytes, 0, bytes.Length);
+ }
+
+ private static uint[] MakeMagnitudeBE(byte[] bytes, int offset, int length)
+ {
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return MakeMagnitudeBE(bytes.AsSpan(offset, length));
+#else
+ int end = offset + length;
+
+ // strip leading zeros
+ int start;
+ for (start = offset; start < end && bytes[start] == 0; start++)
{
- mag[magnitudeIndex] = v;
}
- return mag;
+ int nBytes = end - start;
+ if (nBytes <= 0)
+ return ZeroMagnitude;
+
+ int nInts = (nBytes + BytesPerInt - 1) / BytesPerInt;
+ Debug.Assert(nInts > 0);
+
+ uint[] magnitude = new uint[nInts];
+
+ int first = ((nBytes - 1) % BytesPerInt) + 1;
+ magnitude[0] = Pack.BE_To_UInt32_Low(bytes, start, first);
+ Pack.BE_To_UInt32(bytes, start + first, magnitude, 1, nInts - 1);
+
+ return magnitude;
#endif
}
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- private static uint[] MakeMagnitude(ReadOnlySpan<byte> bytes)
+ private static uint[] MakeMagnitudeBE(ReadOnlySpan<byte> bytes)
{
int end = bytes.Length;
// strip leading zeros
- int firstSignificant;
- for (firstSignificant = 0; firstSignificant < end && bytes[firstSignificant] == 0; firstSignificant++)
+ int start;
+ for (start = 0; start < end && bytes[start] == 0; start++)
{
}
- if (firstSignificant >= end)
+ int nBytes = end - start;
+ if (nBytes <= 0)
return ZeroMagnitude;
- int nInts = (end - firstSignificant + 3) / BytesPerInt;
- int bCount = (end - firstSignificant) % BytesPerInt;
- if (bCount == 0)
+ int nInts = (nBytes + BytesPerInt - 1) / BytesPerInt;
+ Debug.Assert(nInts > 0);
+
+ uint[] magnitude = new uint[nInts];
+
+ int first = ((nBytes - 1) % BytesPerInt) + 1;
+ magnitude[0] = Pack.BE_To_UInt32_Low(bytes.Slice(start, first));
+ Pack.BE_To_UInt32(bytes.Slice(start + first), magnitude.AsSpan(1));
+
+ return magnitude;
+ }
+#endif
+
+ private static uint[] MakeMagnitudeLE(byte[] bytes)
+ {
+ return MakeMagnitudeLE(bytes, 0, bytes.Length);
+ }
+
+ private static uint[] MakeMagnitudeLE(byte[] bytes, int offset, int length)
+ {
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return MakeMagnitudeLE(bytes.AsSpan(offset, length));
+#else
+ // strip leading zeros
+ int last = length;
+ while (--last >= 0 && bytes[offset + last] == 0)
{
- bCount = BytesPerInt;
}
- if (nInts < 1)
+ if (last < 0)
return ZeroMagnitude;
- uint[] mag = new uint[nInts];
+ int nInts = (last + BytesPerInt) / BytesPerInt;
+ Debug.Assert(nInts > 0);
- uint v = 0;
- int magnitudeIndex = 0;
- for (int i = firstSignificant; i < end; ++i)
+ uint[] magnitude = new uint[nInts];
+
+ int partial = last % BytesPerInt;
+ int first = partial + 1;
+ int pos = offset + last - partial;
+
+ magnitude[0] = Pack.LE_To_UInt32_Low(bytes, pos, first);
+ for (int i = 1; i < nInts; ++i)
+ {
+ pos -= BytesPerInt;
+ magnitude[i] = Pack.LE_To_UInt32(bytes, pos);
+ }
+ Debug.Assert(pos == offset);
+
+ return magnitude;
+#endif
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ private static uint[] MakeMagnitudeLE(ReadOnlySpan<byte> bytes)
+ {
+ // strip leading zeros
+ int last = bytes.Length;
+ while (--last >= 0 && bytes[last] == 0)
{
- v <<= 8;
- v |= bytes[i];
- bCount--;
- if (bCount <= 0)
- {
- mag[magnitudeIndex] = v;
- magnitudeIndex++;
- bCount = BytesPerInt;
- v = 0U;
- }
}
- if (magnitudeIndex < mag.Length)
+ if (last < 0)
+ return ZeroMagnitude;
+
+ int nInts = (last + BytesPerInt) / BytesPerInt;
+ Debug.Assert(nInts > 0);
+
+ uint[] magnitude = new uint[nInts];
+
+ int partial = last % BytesPerInt;
+ int first = partial + 1;
+ int pos = last - partial;
+
+ magnitude[0] = Pack.LE_To_UInt32_Low(bytes.Slice(pos, first));
+ for (int i = 1; i < nInts; ++i)
{
- mag[magnitudeIndex] = v;
+ pos -= BytesPerInt;
+ magnitude[i] = Pack.LE_To_UInt32(bytes, pos);
}
+ Debug.Assert(pos == 0);
- return mag;
+ return magnitude;
}
#endif
public BigInteger(int sign, byte[] bytes)
- : this(sign, bytes, 0, bytes.Length)
+ : this(sign, bytes, 0, bytes.Length, true)
+ {
+ }
+
+ public BigInteger(int sign, byte[] bytes, bool bigEndian)
+ : this(sign, bytes, 0, bytes.Length, bigEndian)
{
}
public BigInteger(int sign, byte[] bytes, int offset, int length)
+ : this(sign, bytes, offset, length, true)
+ {
+ }
+
+ public BigInteger(int sign, byte[] bytes, int offset, int length, bool bigEndian)
{
if (sign < -1 || sign > 1)
throw new FormatException("Invalid sign value");
@@ -664,13 +768,20 @@ namespace Org.BouncyCastle.Math
else
{
// copy bytes
- this.magnitude = MakeMagnitude(bytes, offset, length);
+ this.magnitude = bigEndian
+ ? MakeMagnitudeBE(bytes, offset, length)
+ : MakeMagnitudeLE(bytes, offset, length);
this.sign = this.magnitude.Length < 1 ? 0 : sign;
}
}
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
public BigInteger(int sign, ReadOnlySpan<byte> bytes)
+ : this(sign, bytes, true)
+ {
+ }
+
+ public BigInteger(int sign, ReadOnlySpan<byte> bytes, bool bigEndian)
{
if (sign < -1 || sign > 1)
throw new FormatException("Invalid sign value");
@@ -683,7 +794,9 @@ namespace Org.BouncyCastle.Math
else
{
// copy bytes
- this.magnitude = MakeMagnitude(bytes);
+ this.magnitude = bigEndian
+ ? MakeMagnitudeBE(bytes)
+ : MakeMagnitudeLE(bytes);
this.sign = this.magnitude.Length < 1 ? 0 : sign;
}
}
@@ -719,7 +832,7 @@ namespace Org.BouncyCastle.Math
int xBits = BitsPerByte * nBytes - sizeInBits;
b[0] &= (byte)(255U >> xBits);
- this.magnitude = MakeMagnitude(b);
+ this.magnitude = MakeMagnitudeBE(b);
this.sign = this.magnitude.Length < 1 ? 0 : 1;
}
@@ -766,7 +879,7 @@ namespace Org.BouncyCastle.Math
// ensure the trailing bit is 1 (i.e. must be odd)
b[nBytes - 1] |= 1;
- this.magnitude = MakeMagnitude(b);
+ this.magnitude = MakeMagnitudeBE(b);
this.nBits = -1;
if (certainty < 1)
|