diff --git a/crypto/src/crypto/signers/ECGOST3410Signer.cs b/crypto/src/crypto/signers/ECGOST3410Signer.cs
index fd5fa4818..ba6969e39 100644
--- a/crypto/src/crypto/signers/ECGOST3410Signer.cs
+++ b/crypto/src/crypto/signers/ECGOST3410Signer.cs
@@ -68,8 +68,7 @@ namespace Org.BouncyCastle.Crypto.Signers
if (!forSigning)
throw new InvalidOperationException("not initialized for signing");
- byte[] mRev = Arrays.Reverse(message); // conversion is little-endian
- BigInteger e = new BigInteger(1, mRev);
+ BigInteger e = new BigInteger(1, message, bigEndian: false);
ECDomainParameters ec = key.Parameters;
BigInteger n = ec.N;
@@ -113,8 +112,7 @@ namespace Org.BouncyCastle.Crypto.Signers
if (forSigning)
throw new InvalidOperationException("not initialized for verification");
- byte[] mRev = Arrays.Reverse(message); // conversion is little-endian
- BigInteger e = new BigInteger(1, mRev);
+ BigInteger e = new BigInteger(1, message, bigEndian: false);
BigInteger n = key.Parameters.N;
// r in the range [1,n-1]
diff --git a/crypto/src/crypto/signers/GOST3410Signer.cs b/crypto/src/crypto/signers/GOST3410Signer.cs
index 03aab0b04..0d80737d0 100644
--- a/crypto/src/crypto/signers/GOST3410Signer.cs
+++ b/crypto/src/crypto/signers/GOST3410Signer.cs
@@ -61,11 +61,9 @@ namespace Org.BouncyCastle.Crypto.Signers
*
* @param message the message that will be verified later.
*/
- public virtual BigInteger[] GenerateSignature(
- byte[] message)
+ public virtual BigInteger[] GenerateSignature(byte[] message)
{
- byte[] mRev = Arrays.Reverse(message); // conversion is little-endian
- BigInteger m = new BigInteger(1, mRev);
+ BigInteger m = new BigInteger(1, message, bigEndian: false);
Gost3410Parameters parameters = key.Parameters;
BigInteger k;
@@ -89,13 +87,9 @@ namespace Org.BouncyCastle.Crypto.Signers
* the passed in message for standard Gost3410 the message should be a
* Gost3411 hash of the real message to be verified.
*/
- public virtual bool VerifySignature(
- byte[] message,
- BigInteger r,
- BigInteger s)
+ public virtual bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
{
- byte[] mRev = Arrays.Reverse(message); // conversion is little-endian
- BigInteger m = new BigInteger(1, mRev);
+ BigInteger m = new BigInteger(1, message, bigEndian: false);
Gost3410Parameters parameters = key.Parameters;
if (r.SignValue < 0 || parameters.Q.CompareTo(r) <= 0)
diff --git a/crypto/src/crypto/util/Pack.cs b/crypto/src/crypto/util/Pack.cs
index 99c15484c..a4f8a834f 100644
--- a/crypto/src/crypto/util/Pack.cs
+++ b/crypto/src/crypto/util/Pack.cs
@@ -578,6 +578,25 @@ namespace Org.BouncyCastle.Crypto.Utilities
#endif
}
+ internal static uint LE_To_UInt32_High(byte[] bs, int off, int len)
+ {
+ return LE_To_UInt32_Low(bs, off, len) << ((4 - len) << 3);
+ }
+
+ internal static uint LE_To_UInt32_Low(byte[] bs, int off, int len)
+ {
+ Debug.Assert(1 <= len && len <= 4);
+
+ uint result = bs[off];
+ int pos = 0;
+ for (int i = 1; i < len; ++i)
+ {
+ pos += 8;
+ result |= (uint)bs[off + i] << pos;
+ }
+ return result;
+ }
+
internal static void LE_To_UInt32(byte[] bs, int off, uint[] ns)
{
for (int i = 0; i < ns.Length; ++i)
@@ -826,6 +845,27 @@ namespace Org.BouncyCastle.Crypto.Utilities
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static uint LE_To_UInt32_High(ReadOnlySpan<byte> bs)
+ {
+ return LE_To_UInt32_Low(bs) << ((4 - bs.Length) << 3);
+ }
+
+ internal static uint LE_To_UInt32_Low(ReadOnlySpan<byte> bs)
+ {
+ int len = bs.Length;
+ Debug.Assert(1 <= len && len <= 4);
+
+ uint result = bs[0];
+ int pos = 0;
+ for (int i = 1; i < len; ++i)
+ {
+ pos += 8;
+ result |= (uint)bs[i] << pos;
+ }
+ return result;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static ulong LE_To_UInt64(ReadOnlySpan<byte> bs)
{
return BinaryPrimitives.ReadUInt64LittleEndian(bs);
diff --git a/crypto/src/math/BigInteger.cs b/crypto/src/math/BigInteger.cs
index a98955779..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 = MakeMagnitudeBE(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,7 +552,56 @@ namespace Org.BouncyCastle.Math
inverse[index]++;
- this.magnitude = MakeMagnitudeBE(inverse);
+ return MakeMagnitudeBE(inverse);
+ }
+
+ private static uint[] InitLE(byte[] bytes, int offset, int length, out int sign)
+ {
+ int end = offset + length;
+
+ // 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;
+ }
+
+ sign = -1;
+
+ // strip leading sign bytes
+ int last = length;
+ while (--last >= 0 && bytes[offset + last] == byte.MaxValue)
+ {
+ }
+
+ if (last < 0)
+ return One.magnitude;
+
+ int numBytes = last + 1;
+
+#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)
+ {
+ inverse[i] = (byte)~bytes[offset + i];
+ }
+
+ int index = 0;
+ while (inverse[index] == byte.MaxValue)
+ {
+ inverse[index++] = byte.MinValue;
+ }
+
+ inverse[index]++;
+
+ return MakeMagnitudeLE(inverse);
}
private static uint[] MakeMagnitudeBE(byte[] bytes)
@@ -600,12 +667,95 @@ namespace Org.BouncyCastle.Math
}
#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)
+ {
+ }
+
+ 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 = 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)
+ {
+ }
+
+ 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)
+ {
+ pos -= BytesPerInt;
+ magnitude[i] = Pack.LE_To_UInt32(bytes, pos);
+ }
+ Debug.Assert(pos == 0);
+
+ 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");
@@ -618,13 +768,20 @@ namespace Org.BouncyCastle.Math
else
{
// copy bytes
- this.magnitude = MakeMagnitudeBE(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");
@@ -637,7 +794,9 @@ namespace Org.BouncyCastle.Math
else
{
// copy bytes
- this.magnitude = MakeMagnitudeBE(bytes);
+ this.magnitude = bigEndian
+ ? MakeMagnitudeBE(bytes)
+ : MakeMagnitudeLE(bytes);
this.sign = this.magnitude.Length < 1 ? 0 : sign;
}
}
diff --git a/crypto/src/math/raw/Nat.cs b/crypto/src/math/raw/Nat.cs
index 61d060b4e..f4d91b180 100644
--- a/crypto/src/math/raw/Nat.cs
+++ b/crypto/src/math/raw/Nat.cs
@@ -2747,14 +2747,9 @@ namespace Org.BouncyCastle.Math.Raw
? stackalloc byte[bsLen]
: new byte[bsLen];
- int xPos = len;
- Span<byte> t = bs;
- while (--xPos >= 0)
- {
- Pack.UInt32_To_BE(x[xPos], t);
- t = t[4..];
- }
- return new BigInteger(1, bs);
+ Pack.UInt32_To_LE(x, bs);
+
+ return new BigInteger(1, bs, bigEndian: false);
}
#endif
diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs
index 38e571cd6..d6fa87943 100644
--- a/crypto/src/security/PrivateKeyFactory.cs
+++ b/crypto/src/security/PrivateKeyFactory.cs
@@ -151,7 +151,7 @@ namespace Org.BouncyCastle.Security
Asn1OctetString privEnc = keyInfo.PrivateKeyData;
if (privEnc.GetOctets().Length == 32 || privEnc.GetOctets().Length == 64)
{
- d = new BigInteger(1, Arrays.Reverse(privEnc.GetOctets()));
+ d = new BigInteger(1, privEnc.GetOctets(), bigEndian: false);
}
else
{
@@ -162,8 +162,8 @@ namespace Org.BouncyCastle.Security
}
else
{
- byte[] dVal = Arrays.Reverse(Asn1OctetString.GetInstance(privKey).GetOctets());
- d = new BigInteger(1, dVal);
+ byte[] dVal = Asn1OctetString.GetInstance(privKey).GetOctets();
+ d = new BigInteger(1, dVal, bigEndian: false);
}
}
}
@@ -233,7 +233,7 @@ namespace Org.BouncyCastle.Security
}
else
{
- x = new BigInteger(1, Arrays.Reverse(Asn1OctetString.GetInstance(privKey).GetOctets()));
+ x = new BigInteger(1, Asn1OctetString.GetInstance(privKey).GetOctets(), bigEndian: false);
}
return new Gost3410PrivateKeyParameters(x, gostParams.PublicKeyParamSet);
@@ -280,8 +280,7 @@ namespace Org.BouncyCastle.Security
Asn1OctetString privEnc = keyInfo.PrivateKeyData;
if (privEnc.GetOctets().Length == 32 || privEnc.GetOctets().Length == 64)
{
- byte[] dVal = Arrays.Reverse(privEnc.GetOctets());
- d = new BigInteger(1, dVal);
+ d = new BigInteger(1, privEnc.GetOctets(), bigEndian: false);
}
else
{
@@ -292,8 +291,8 @@ namespace Org.BouncyCastle.Security
}
else
{
- byte[] dVal = Arrays.Reverse(Asn1OctetString.GetInstance(privKey).GetOctets());
- d = new BigInteger(1, dVal);
+ byte[] dVal = Asn1OctetString.GetInstance(privKey).GetOctets();
+ d = new BigInteger(1, dVal, bigEndian: false);
}
}
}
diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs
index 03cabbb13..d3ecef5c7 100644
--- a/crypto/src/security/PublicKeyFactory.cs
+++ b/crypto/src/security/PublicKeyFactory.cs
@@ -203,9 +203,9 @@ namespace Org.BouncyCastle.Security
throw new ArgumentException("error recovering GOST3410_94 public key", e);
}
- byte[] keyBytes = Arrays.Reverse(key.GetOctets()); // was little endian
+ byte[] keyBytes = key.GetOctets();
- BigInteger y = new BigInteger(1, keyBytes);
+ BigInteger y = new BigInteger(1, keyBytes, bigEndian: false);
return new Gost3410PublicKeyParameters(y, algParams.PublicKeyParamSet);
}
|