diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-10-05 15:39:23 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-10-05 15:39:23 +0700 |
commit | 57a13b4f15c5a5b8f495b83b5ea825716a199935 (patch) | |
tree | 0f454ba2b3a4f542534ab96db358251f4ca85bae /crypto/src/math | |
parent | Various span usage in TLS code (diff) | |
download | BouncyCastle.NET-ed25519-57a13b4f15c5a5b8f495b83b5ea825716a199935.tar.xz |
BigInteger in-place conversions
Diffstat (limited to 'crypto/src/math')
-rw-r--r-- | crypto/src/math/BigInteger.cs | 116 |
1 files changed, 111 insertions, 5 deletions
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); |