diff --git a/crypto/src/math/BigInteger.cs b/crypto/src/math/BigInteger.cs
index fc4e15486..4cb220d00 100644
--- a/crypto/src/math/BigInteger.cs
+++ b/crypto/src/math/BigInteger.cs
@@ -14,7 +14,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math
{
[Serializable]
- public class BigInteger
+ public sealed class BigInteger
{
// The first few odd primes
/*
@@ -237,8 +237,7 @@ namespace Org.BouncyCastle.Math
this.mQuote = 0;
}
- private static int GetByteLength(
- int nBits)
+ private static int GetByteLength(int nBits)
{
return (nBits + BitsPerByte - 1) / BitsPerByte;
}
@@ -3169,18 +3168,41 @@ namespace Org.BouncyCastle.Math
return Subtract(0, res, 0, lilMag);
}
+ public int GetLengthofByteArray()
+ {
+ return GetByteLength(BitLength + 1);
+ }
+
+ public int GetLengthofByteArrayUnsigned()
+ {
+ return GetByteLength(sign < 0 ? BitLength + 1 : BitLength);
+ }
+
public byte[] ToByteArray()
{
return ToByteArray(false);
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void ToByteArray(Span<byte> output)
+ {
+ ToByteArray(false, output);
+ }
+#endif
+
public byte[] ToByteArrayUnsigned()
{
return ToByteArray(true);
}
- private byte[] ToByteArray(
- bool unsigned)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void ToByteArrayUnsigned(Span<byte> output)
+ {
+ ToByteArray(true, output);
+ }
+#endif
+
+ private byte[] ToByteArray(bool unsigned)
{
if (sign == 0)
return unsigned ? ZeroEncoding : new byte[1];
@@ -3259,6 +3281,90 @@ namespace Org.BouncyCastle.Math
return bytes;
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ private void ToByteArray(bool unsigned, Span<byte> output)
+ {
+ if (sign == 0)
+ {
+ if (!unsigned)
+ {
+ output[0] = 0;
+ }
+ return;
+ }
+
+ int nBits = (unsigned && sign > 0) ? BitLength : BitLength + 1;
+
+ int nBytes = GetByteLength(nBits);
+ if (nBytes > output.Length)
+ throw new ArgumentException("insufficient space", nameof(output));
+
+ int magIndex = magnitude.Length;
+ int bytesIndex = nBytes;
+
+ if (sign > 0)
+ {
+ while (magIndex > 1)
+ {
+ uint mag = (uint) magnitude[--magIndex];
+ output[--bytesIndex] = (byte) mag;
+ output[--bytesIndex] = (byte)(mag >> 8);
+ output[--bytesIndex] = (byte)(mag >> 16);
+ output[--bytesIndex] = (byte)(mag >> 24);
+ }
+
+ uint lastMag = (uint)magnitude[0];
+ while (lastMag > byte.MaxValue)
+ {
+ output[--bytesIndex] = (byte)lastMag;
+ lastMag >>= 8;
+ }
+
+ output[--bytesIndex] = (byte)lastMag;
+ }
+ else // sign < 0
+ {
+ bool carry = true;
+
+ while (magIndex > 1)
+ {
+ uint mag = ~((uint)magnitude[--magIndex]);
+
+ if (carry)
+ {
+ carry = (++mag == uint.MinValue);
+ }
+
+ output[--bytesIndex] = (byte) mag;
+ output[--bytesIndex] = (byte)(mag >> 8);
+ output[--bytesIndex] = (byte)(mag >> 16);
+ output[--bytesIndex] = (byte)(mag >> 24);
+ }
+
+ uint lastMag = (uint)magnitude[0];
+
+ if (carry)
+ {
+ // Never wraps because magnitude[0] != 0
+ --lastMag;
+ }
+
+ while (lastMag > byte.MaxValue)
+ {
+ output[--bytesIndex] = (byte)~lastMag;
+ lastMag >>= 8;
+ }
+
+ output[--bytesIndex] = (byte)~lastMag;
+
+ if (bytesIndex > 0)
+ {
+ output[--bytesIndex] = byte.MaxValue;
+ }
+ }
+ }
+#endif
+
public override string ToString()
{
return ToString(10);
diff --git a/crypto/src/util/BigIntegers.cs b/crypto/src/util/BigIntegers.cs
index 1d706beb4..44c9e32a7 100644
--- a/crypto/src/util/BigIntegers.cs
+++ b/crypto/src/util/BigIntegers.cs
@@ -22,8 +22,7 @@ namespace Org.BouncyCastle.Utilities
* @param value the value to be converted.
* @return a byte array without a leading zero byte if present in the signed encoding.
*/
- public static byte[] AsUnsignedByteArray(
- BigInteger n)
+ public static byte[] AsUnsignedByteArray(BigInteger n)
{
return n.ToByteArrayUnsigned();
}
@@ -37,6 +36,16 @@ namespace Org.BouncyCastle.Utilities
*/
public static byte[] AsUnsignedByteArray(int length, BigInteger n)
{
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ int bytesLength = n.GetLengthofByteArrayUnsigned();
+
+ if (bytesLength > length)
+ throw new ArgumentException("standard length exceeded", nameof(n));
+
+ byte[] bytes = new byte[length];
+ n.ToByteArrayUnsigned(bytes.AsSpan(length - bytesLength));
+ return bytes;
+#else
byte[] bytes = n.ToByteArrayUnsigned();
int bytesLength = bytes.Length;
@@ -44,18 +53,19 @@ namespace Org.BouncyCastle.Utilities
return bytes;
if (bytesLength > length)
- throw new ArgumentException("standard length exceeded", "n");
+ throw new ArgumentException("standard length exceeded", nameof(n));
byte[] tmp = new byte[length];
Array.Copy(bytes, 0, tmp, length - bytesLength, bytesLength);
return tmp;
+#endif
}
/**
* Write the passed in value as unsigned bytes to the specified buffer range, padded with
* leading zeros as necessary.
*
- * @param value
+ * @param n
* the value to be converted.
* @param buf
* the buffer to which the value is written.
@@ -64,50 +74,33 @@ namespace Org.BouncyCastle.Utilities
* @param len
* the fixed length of data written (possibly padded with leading zeros).
*/
- public static void AsUnsignedByteArray(BigInteger value, byte[] buf, int off, int len)
+ public static void AsUnsignedByteArray(BigInteger n, byte[] buf, int off, int len)
{
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- AsUnsignedByteArray(value, buf.AsSpan(off, len));
+ AsUnsignedByteArray(n, buf.AsSpan(off, len));
#else
- byte[] bytes = value.ToByteArrayUnsigned();
- if (bytes.Length == len)
- {
- Array.Copy(bytes, 0, buf, off, len);
- return;
- }
-
- int start = bytes[0] == 0 ? 1 : 0;
- int count = bytes.Length - start;
+ byte[] bytes = n.ToByteArrayUnsigned();
+ int bytesLength = bytes.Length;
- if (count > len)
- throw new ArgumentException("standard length exceeded for value");
+ if (bytesLength > len)
+ throw new ArgumentException("standard length exceeded", nameof(n));
- int padLen = len - count;
+ int padLen = len - bytesLength;
Arrays.Fill(buf, off, off + padLen, 0);
- Array.Copy(bytes, start, buf, off + padLen, count);
+ Array.Copy(bytes, 0, buf, off + padLen, bytesLength);
#endif
}
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public static void AsUnsignedByteArray(BigInteger value, Span<byte> buf)
+ public static void AsUnsignedByteArray(BigInteger n, Span<byte> buf)
{
- int len = buf.Length;
- byte[] bytes = value.ToByteArrayUnsigned();
- if (bytes.Length == len)
- {
- bytes.CopyTo(buf);
- return;
- }
+ int bytesLength = n.GetLengthofByteArrayUnsigned();
- int start = bytes[0] == 0 ? 1 : 0;
- int count = bytes.Length - start;
+ if (bytesLength > buf.Length)
+ throw new ArgumentException("standard length exceeded", nameof(n));
- if (count > len)
- throw new ArgumentException("standard length exceeded for value");
-
- int padLen = len - count;
- buf[..padLen].Fill(0x00);
- bytes.AsSpan(start, count).CopyTo(buf[padLen..]);
+ buf[..^bytesLength].Fill(0x00);
+ n.ToByteArrayUnsigned(buf[^bytesLength..]);
}
#endif
@@ -209,9 +202,14 @@ namespace Org.BouncyCastle.Utilities
return Nat.ToBigInteger(len, z);
}
+ public static int GetByteLength(BigInteger n)
+ {
+ return n.GetLengthofByteArray();
+ }
+
public static int GetUnsignedByteLength(BigInteger n)
{
- return (n.BitLength + 7) / 8;
+ return n.GetLengthofByteArrayUnsigned();
}
}
}
|