diff --git a/src/Renci.SshNet/Common/BigInteger.cs b/src/Renci.SshNet/Common/BigInteger.cs deleted file mode 100644 index 57c3def90..000000000 --- a/src/Renci.SshNet/Common/BigInteger.cs +++ /dev/null @@ -1,4956 +0,0 @@ -#pragma warning disable SA1028 // Code should not contain trailing whitespace -// -// System.Numerics.BigInteger -// -// Authors: -// Rodrigo Kumpera (rkumpera@novell.com) -// Marek Safar -// -// Copyright (C) 2010 Novell, Inc (http://www.novell.com) -// Copyright (C) 2014 Xamarin Inc (http://www.xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -// A big chuck of code comes the DLR (as hosted in http://ironpython.codeplex.com), -// which has the following License: -// -/* **************************************************************************** -* -* Copyright (c) Microsoft Corporation. -* -* This source code is subject to terms and conditions of the Microsoft Public License. A -* copy of the license can be found in the License.html file at the root of this distribution. If -* you cannot locate the Microsoft Public License, please send an email to -* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound -* by the terms of the Microsoft Public License. -* -* You must not remove this notice, or any other, from this software. -* -* -* ***************************************************************************/ -#pragma warning restore SA1028 // Code should not contain trailing whitespace - -using System; -using System.Collections.Generic; -using System.Globalization; - -using Renci.SshNet.Abstractions; - -/* - * Optimization: - * - Have proper popcount function for IsPowerOfTwo - * - Use unsafe ops to avoid bounds check - * - CoreAdd could avoid some resizes by checking for equal sized array that top overflow - * - For bitwise operators, hoist the conditionals out of their main loop - * - Optimize BitScanBackward - * - Use a carry variable to make shift opts do half the number of array ops. - * -Schoolbook multiply is O(n^2), use Karatsuba /Toom-3 for large numbers - */ -namespace Renci.SshNet.Common -{ - /// - /// Represents an arbitrarily large signed integer. - /// - public struct BigInteger : IComparable, IFormattable, IComparable, IEquatable - { - private const ulong Base = 0x100000000; - private const int Bias = 1075; - private const int DecimalSignMask = unchecked((int)0x80000000); - - private static readonly BigInteger ZeroSingleton = new BigInteger(0); - private static readonly BigInteger OneSingleton = new BigInteger(1); - private static readonly BigInteger MinusOneSingleton = new BigInteger(-1); - - // LSB on [0] - private readonly uint[] _data; - private readonly short _sign; - - #region SSH.NET additions - - /// - /// Gets number of bits used by the number. - /// - /// - /// The number of the bit used. - /// - public readonly int BitLength - { - get - { - if (_sign == 0) - { - return 0; - } - - var msbIndex = _data.Length - 1; - - while (_data[msbIndex] == 0) - { - msbIndex--; - } - - var msbBitCount = BitScanBackward(_data[msbIndex]) + 1; - - return (msbIndex * 4 * 8) + msbBitCount + ((_sign > 0) ? 0 : 1); - } - } - - /// - /// Mods the inverse. - /// - /// The bi. - /// The modulus. - /// - /// Modulus inverted number. - /// - public static BigInteger ModInverse(BigInteger bi, BigInteger modulus) - { - BigInteger a = modulus, b = bi % modulus; - BigInteger p0 = 0, p1 = 1; - - while (!b.IsZero) - { - if (b.IsOne) - { - return p1; - } - - p0 += (a / b) * p1; - a %= b; - - if (a.IsZero) - { - break; - } - - if (a.IsOne) - { - return modulus - p0; - } - - p1 += (b / a) * p0; - b %= a; - } - - return 0; - } - - /// - /// Returns positive remainder that results from division with two specified values. - /// - /// The value to be divided. - /// The value to divide by. - /// - /// Positive remainder that results from the division. - /// - public static BigInteger PositiveMod(BigInteger dividend, BigInteger divisor) - { - var result = dividend % divisor; - - if (result < 0) - { - result += divisor; - } - - return result; - } - - /// - /// Generates a new, random of the specified length. - /// - /// The number of bits for the new number. - /// A random number of the specified length. - public static BigInteger Random(int bitLength) - { - var bytesArray = CryptoAbstraction.GenerateRandom((bitLength / 8) + (((bitLength % 8) > 0) ? 1 : 0)); - bytesArray[bytesArray.Length - 1] = (byte)(bytesArray[bytesArray.Length - 1] & 0x7F); // Ensure not a negative value - return new BigInteger(bytesArray); - } - - #endregion SSH.NET additions - - private BigInteger(short sign, uint[] data) - { - _sign = sign; - _data = data; - } - - /// - /// Initializes a new instance of the structure using a 32-bit signed integer value. - /// - /// A 32-bit signed integer. - public BigInteger(int value) - { - if (value == 0) - { - _sign = 0; - _data = null; - } - else if (value > 0) - { - _sign = 1; - _data = new[] { (uint)value }; - } - else - { - _sign = -1; - _data = new[] { (uint)-value }; - } - } - - /// - /// Initializes a new instance of the structure using an unsigned 32-bit integer value. - /// - /// An unsigned 32-bit integer value. - [CLSCompliant(false)] - public BigInteger(uint value) - { - if (value == 0) - { - _sign = 0; - _data = null; - } - else - { - _sign = 1; - _data = new[] { value }; - } - } - - /// - /// Initializes a new instance of the structure using a 64-bit signed integer value. - /// - /// A 64-bit signed integer. - public BigInteger(long value) - { - if (value == 0) - { - _sign = 0; - _data = null; - } - else if (value > 0) - { - _sign = 1; - var low = (uint)value; - var high = (uint)(value >> 32); - - _data = new uint[high != 0 ? 2 : 1]; - _data[0] = low; - if (high != 0) - { - _data[1] = high; - } - } - else - { - _sign = -1; - value = -value; - var low = (uint)value; - var high = (uint)((ulong)value >> 32); - - _data = new uint[high != 0 ? 2 : 1]; - _data[0] = low; - if (high != 0) - { - _data[1] = high; - } - } - } - - /// - /// Initializes a new instance of the structure with an unsigned 64-bit integer value. - /// - /// An unsigned 64-bit integer. - [CLSCompliant(false)] - public BigInteger(ulong value) - { - if (value == 0) - { - _sign = 0; - _data = null; - } - else - { - _sign = 1; - var low = (uint)value; - var high = (uint)(value >> 32); - - _data = new uint[high != 0 ? 2 : 1]; - _data[0] = low; - if (high != 0) - { - _data[1] = high; - } - } - } - - /// - /// Initializes a new instance of the structure using a double-precision floating-point value. - /// - /// A double-precision floating-point value. - public BigInteger(double value) - { - if (double.IsNaN(value) || double.IsInfinity(value)) - { - throw new OverflowException(); - } - - var bytes = BitConverter.GetBytes(value); - var mantissa = Mantissa(bytes); - if (mantissa == 0) - { - // 1.0 * 2**exp, we have a power of 2 - int exponent = Exponent(bytes); - if (exponent == 0) - { - _sign = 0; - _data = null; - return; - } - - var res = Negative(bytes) ? MinusOne : One; - res <<= exponent - 0x3ff; - _sign = res._sign; - _data = res._data; - } - else - { - // 1.mantissa * 2**exp - int exponent = Exponent(bytes); - mantissa |= 0x10000000000000ul; - BigInteger res = mantissa; - res = exponent > Bias ? res << (exponent - Bias) : res >> (Bias - exponent); - - _sign = (short)(Negative(bytes) ? -1 : 1); - _data = res._data; - } - } - - /// - /// Initializes a new instance of the structure using a single-precision floating-point value. - /// - /// A single-precision floating-point value. - public BigInteger(float value) - : this((double)value) - { - } - - /// - /// Initializes a new instance of the structure using a value. - /// - /// A decimal number. - public BigInteger(decimal value) - { - // First truncate to get scale to 0 and extract bits - var bits = decimal.GetBits(decimal.Truncate(value)); - - var size = 3; - while (size > 0 && bits[size - 1] == 0) - { - size--; - } - - if (size == 0) - { - _sign = 0; - _data = null; - return; - } - - _sign = (short)((bits[3] & DecimalSignMask) != 0 ? -1 : 1); - - _data = new uint[size]; - _data[0] = (uint)bits[0]; - if (size > 1) - { - _data[1] = (uint)bits[1]; - } - - if (size > 2) - { - _data[2] = (uint)bits[2]; - } - } - - /// - /// Initializes a new instance of the structure using the values in a byte array. - /// - /// An array of values in little-endian order. - /// is . - [CLSCompliant(false)] - public BigInteger(byte[] value) - { - if (value is null) - { - throw new ArgumentNullException(nameof(value)); - } - - var len = value.Length; - - if (len == 0 || (len == 1 && value[0] == 0)) - { - _sign = 0; - _data = null; - return; - } - - if ((value[len - 1] & 0x80) != 0) - { - _sign = -1; - } - else - { - _sign = 1; - } - -#pragma warning disable CA1508 // Avoid dead conditional code | this is the following bug in the analyzer rule: https://github.com/dotnet/roslyn-analyzers/issues/6991 - if (_sign == 1) -#pragma warning restore CA1508 // Avoid dead conditional code - { - while (value[len - 1] == 0) - { - if (--len == 0) - { - _sign = 0; - _data = null; - return; - } - } - - int size; - var fullWords = size = len / 4; - if ((len & 0x3) != 0) - { - ++size; - } - - _data = new uint[size]; - var j = 0; - for (var i = 0; i < fullWords; ++i) - { - _data[i] = (uint)value[j++] | - (uint)(value[j++] << 8) | - (uint)(value[j++] << 16) | - (uint)(value[j++] << 24); - } - - size = len & 0x3; - if (size > 0) - { - var idx = _data.Length - 1; - for (var i = 0; i < size; ++i) - { - _data[idx] |= (uint)(value[j++] << (i * 8)); - } - } - } - else - { - int size; - var fullWords = size = len / 4; - if ((len & 0x3) != 0) - { - ++size; - } - - _data = new uint[size]; - - uint word, borrow = 1; - ulong sub; - var j = 0; - - for (var i = 0; i < fullWords; ++i) - { - word = (uint)value[j++] | - (uint)(value[j++] << 8) | - (uint)(value[j++] << 16) | - (uint)(value[j++] << 24); - - sub = (ulong)word - borrow; - word = (uint)sub; - borrow = (uint)(sub >> 32) & 0x1u; - _data[i] = ~word; - } - - size = len & 0x3; - - if (size > 0) - { - word = 0; - uint storeMask = 0; - for (var i = 0; i < size; ++i) - { - word |= (uint)(value[j++] << (i * 8)); - storeMask = (storeMask << 8) | 0xFF; - } - - sub = word - borrow; - word = (uint)sub; - borrow = (uint)(sub >> 32) & 0x1u; - - if ((~word & storeMask) == 0) - { - Array.Resize(ref _data, _data.Length - 1); - } - else - { - _data[_data.Length - 1] = ~word & storeMask; - } - } - - if (borrow != 0) - { -#pragma warning disable CA2201 // Do not raise reserved exception types - throw new Exception("non zero final carry"); -#pragma warning restore CA2201 // Do not raise reserved exception types - } - } - } - - private static bool Negative(byte[] v) - { - return (v[7] & 0x80) != 0; - } - - private static ushort Exponent(byte[] v) - { - return (ushort)((((ushort)(v[7] & 0x7F)) << (ushort)4) | (((ushort)(v[6] & 0xF0)) >> 4)); - } - - private static ulong Mantissa(byte[] v) - { - var i1 = (uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24); - var i2 = (uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16); - - return (ulong)i1 | ((ulong)i2 << 32); - } - - /// - /// Gets a value indicating whether the value of the current object is an even number. - /// - /// - /// if the value of the object is an even number; otherwise, . - /// - public readonly bool IsEven - { - get { return _sign == 0 || (_data[0] & 0x1) == 0; } - } - - /// - /// Gets a value indicating whether the value of the current object is . - /// - /// - /// if the value of the object is ; - /// otherwise, . - /// - public readonly bool IsOne - { - get { return _sign == 1 && _data.Length == 1 && _data[0] == 1; } - } - - // Gem from Hacker's Delight - // Returns the number of bits set in @x - private static int PopulationCount(uint x) - { - x -= (x >> 1) & 0x55555555; - x = (x & 0x33333333) + ((x >> 2) & 0x33333333); - x = (x + (x >> 4)) & 0x0F0F0F0F; - x += x >> 8; - x += x >> 16; - return (int)(x & 0x0000003F); - } - - /// - /// Returns the number of bits set in . - /// - /// - /// The number of bits set in . - /// - /// - /// Based on code by Zilong Tan on Ulib released under MIT license. - /// - private static int PopulationCount(ulong x) - { - x -= (x >> 1) & 0x5555555555555555UL; - x = (x & 0x3333333333333333UL) + ((x >> 2) & 0x3333333333333333UL); - x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fUL; - return (int)((x * 0x0101010101010101UL) >> 56); - } - - private static int LeadingZeroCount(uint value) - { - value |= value >> 1; - value |= value >> 2; - value |= value >> 4; - value |= value >> 8; - value |= value >> 16; - return 32 - PopulationCount(value); // 32 = bits in uint - } - - private static int LeadingZeroCount(ulong value) - { - value |= value >> 1; - value |= value >> 2; - value |= value >> 4; - value |= value >> 8; - value |= value >> 16; - value |= value >> 32; - return 64 - PopulationCount(value); // 64 = bits in ulong - } - - private static double BuildDouble(int sign, ulong mantissa, int exponent) - { - const int exponentBias = 1023; - const int mantissaLength = 52; - const int exponentLength = 11; - const int maxExponent = 2046; - const long mantissaMask = 0xfffffffffffffL; - const long exponentMask = 0x7ffL; - const ulong negativeMark = 0x8000000000000000uL; - - if (sign == 0 || mantissa == 0) - { - return 0.0; - } - - exponent += exponentBias + mantissaLength; - var offset = LeadingZeroCount(mantissa) - exponentLength; - if (exponent - offset > maxExponent) - { - return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity; - } - - if (offset < 0) - { - mantissa >>= -offset; - exponent += -offset; - } - else if (offset >= exponent) - { - mantissa <<= exponent - 1; - exponent = 0; - } - else - { - mantissa <<= offset; - exponent -= offset; - } - - mantissa &= mantissaMask; - - if ((exponent & exponentMask) == exponent) - { - unchecked - { - var bits = mantissa | ((ulong)exponent << mantissaLength); - if (sign < 0) - { - bits |= negativeMark; - } - - return BitConverter.Int64BitsToDouble((long)bits); - } - } - - return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity; - } - - /// - /// Gets a value Indicating whether the value of the current object is a power of two. - /// - /// - /// if the value of the object is a power of two; - /// otherwise, . - /// - public readonly bool IsPowerOfTwo - { - get - { - if (_sign != 1) - { - return false; - } - - var foundBit = false; - - // This function is pop count == 1 for positive numbers - foreach (var bit in _data) - { - var p = PopulationCount(bit); - if (p > 0) - { - if (p > 1 || foundBit) - { - return false; - } - - foundBit = true; - } - } - - return foundBit; - } - } - - /// - /// Gets a value indicating whether the value of the current object is . - /// - /// - /// if the value of the object is ; - /// otherwise, . - /// - public readonly bool IsZero - { - get { return _sign == 0; } - } - - /// - /// Gets a number that indicates the sign (negative, positive, or zero) of the current object. - /// - /// - /// A number that indicates the sign of the object. - /// - public readonly int Sign - { - get { return _sign; } - } - - /// - /// Gets a value that represents the number negative one (-1). - /// - /// - /// An integer whose value is negative one (-1). - /// - public static BigInteger MinusOne - { - get { return MinusOneSingleton; } - } - - /// - /// Gets a value that represents the number one (1). - /// - /// - /// An object whose value is one (1). - /// - public static BigInteger One - { - get { return OneSingleton; } - } - - /// - /// Gets a value that represents the number 0 (zero). - /// - /// - /// An integer whose value is 0 (zero). - /// - public static BigInteger Zero - { - get { return ZeroSingleton; } - } - - /// - /// Defines an explicit conversion of a object to a 32-bit signed integer value. - /// - /// The value to convert to a 32-bit signed integer. - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator int(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (value._data is null) - { - return 0; - } - - if (value._data.Length > 1) - { - throw new OverflowException(); - } - - var data = value._data[0]; - - if (value._sign == 1) - { - if (data > (uint)int.MaxValue) - { - throw new OverflowException(); - } - - return (int)data; - } - - if (value._sign == -1) - { - if (data > 0x80000000u) - { - throw new OverflowException(); - } - - return -(int)data; - } - - return 0; - } - - /// - /// Defines an explicit conversion of a object to an unsigned 32-bit integer value. - /// - /// The value to convert to an unsigned 32-bit integer. - /// - /// An object that contains the value of the parameter. - /// - [CLSCompliant(false)] -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator uint(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (value._data is null) - { - return 0; - } - - if (value._data.Length > 1 || value._sign == -1) - { - throw new OverflowException(); - } - - return value._data[0]; - } - - /// - /// Defines an explicit conversion of a object to a 16-bit signed integer value. - /// - /// The value to convert to a 16-bit signed integer. - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator short(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - var val = (int)value; - if (val is < short.MinValue or > short.MaxValue) - { - throw new OverflowException(); - } - - return (short)val; - } - - /// - /// Defines an explicit conversion of a object to a 16-bit unsigned integer value. - /// - /// The value to convert to a 16-bit unsigned integer. - /// - /// An object that contains the value of the parameter. - /// - [CLSCompliant(false)] -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator ushort(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - var val = (uint)value; - if (val > ushort.MaxValue) - { - throw new OverflowException(); - } - - return (ushort)val; - } - - /// - /// Defines an explicit conversion of a object to an unsigned byte value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator byte(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - var val = (uint)value; - if (val > byte.MaxValue) - { - throw new OverflowException(); - } - - return (byte)val; - } - - /// - /// Defines an explicit conversion of a object to a signed 8-bit value. - /// - /// The value to convert to a signed 8-bit value. - /// - /// An object that contains the value of the parameter. - /// - [CLSCompliant(false)] -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator sbyte(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - var val = (int)value; - if (val is < sbyte.MinValue or > sbyte.MaxValue) - { - throw new OverflowException(); - } - - return (sbyte)val; - } - - /// - /// Defines an explicit conversion of a object to a 64-bit signed integer value. - /// - /// The value to convert to a 64-bit signed integer. - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator long(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (value._data is null) - { - return 0; - } - - if (value._data.Length > 2) - { - throw new OverflowException(); - } - - var low = value._data[0]; - - if (value._data.Length == 1) - { - if (value._sign == 1) - { - return (long)low; - } - - var res = (long)low; - return -res; - } - - var high = value._data[1]; - - if (value._sign == 1) - { - if (high >= 0x80000000u) - { - throw new OverflowException(); - } - - return (((long)high) << 32) | low; - } - - /* - We cannot represent negative numbers smaller than long.MinValue. - Those values are encoded into what look negative numbers, so negating - them produces a positive value, that's why it's safe to check for that - condition. - - long.MinValue works fine since it's bigint encoding looks like a negative - number, but since long.MinValue == -long.MinValue, we're good. - */ - - var result = -((((long)high) << 32) | (long)low); - if (result > 0) - { - throw new OverflowException(); - } - - return result; - } - - /// - /// Defines an explicit conversion of a object to an unsigned 64-bit integer value. - /// - /// The value to convert to an unsigned 64-bit integer. - /// - /// An object that contains the value of the parameter. - /// - [CLSCompliant(false)] -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator ulong(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (value._data is null) - { - return 0; - } - - if (value._data.Length > 2 || value._sign == -1) - { - throw new OverflowException(); - } - - var low = value._data[0]; - if (value._data.Length == 1) - { - return low; - } - - var high = value._data[1]; - return (((ulong)high) << 32) | low; - } - - /// - /// Defines an explicit conversion of a object to a value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator double(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (value._data is null) - { - return 0.0; - } - - switch (value._data.Length) - { - case 1: - return BuildDouble(value._sign, value._data[0], 0); - case 2: - return BuildDouble(value._sign, (ulong)value._data[1] << 32 | (ulong)value._data[0], 0); - default: - var index = value._data.Length - 1; - var word = value._data[index]; - var mantissa = ((ulong)word << 32) | value._data[index - 1]; - var missing = LeadingZeroCount(word) - 11; // 11 = bits in exponent - if (missing > 0) - { - // add the missing bits from the next word - mantissa = (mantissa << missing) | (value._data[index - 2] >> (32 - missing)); - } - else - { - mantissa >>= -missing; - } - - return BuildDouble(value._sign, mantissa, ((value._data.Length - 2) * 32) - missing); - } - } - - /// - /// Defines an explicit conversion of a object to a single-precision floating-point value. - /// - /// The value to convert to a single-precision floating-point value. - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator float(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - return (float)(double)value; - } - - /// - /// Defines an explicit conversion of a object to a value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator decimal(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (value._data is null) - { - return decimal.Zero; - } - - var data = value._data; - if (data.Length > 3) - { - throw new OverflowException(); - } - - int lo = 0, mi = 0, hi = 0; - if (data.Length > 2) - { - hi = (int)data[2]; - } - - if (data.Length > 1) - { - mi = (int)data[1]; - } - - if (data.Length > 0) - { - lo = (int)data[0]; - } - - return new decimal(lo, mi, hi, value._sign < 0, 0); - } - - /// - /// Defines an implicit conversion of a signed 32-bit integer to a value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static implicit operator BigInteger(int value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - return new BigInteger(value); - } - - /// - /// Defines an implicit conversion of a 32-bit unsigned integer to a value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// - [CLSCompliant(false)] -#pragma warning disable CA2225 // Operator overloads have named alternates - public static implicit operator BigInteger(uint value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - return new BigInteger(value); - } - - /// - /// Defines an implicit conversion of a signed 16-bit integer to a BigInteger value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static implicit operator BigInteger(short value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - return new BigInteger(value); - } - - /// - /// Defines an implicit conversion of a 16-bit unsigned integer to a value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// - [CLSCompliant(false)] -#pragma warning disable CA2225 // Operator overloads have named alternates - public static implicit operator BigInteger(ushort value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - return new BigInteger(value); - } - - /// - /// Defines an implicit conversion of an unsigned byte to a value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static implicit operator BigInteger(byte value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - return new BigInteger(value); - } - - /// - /// Defines an implicit conversion of a signed byte to a value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// - [CLSCompliant(false)] -#pragma warning disable CA2225 // Operator overloads have named alternates - public static implicit operator BigInteger(sbyte value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - return new BigInteger(value); - } - - /// - /// Defines an implicit conversion of a signed 64-bit integer to a value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static implicit operator BigInteger(long value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - return new BigInteger(value); - } - - /// - /// Defines an implicit conversion of a 64-bit unsigned integer to a value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// - [CLSCompliant(false)] -#pragma warning disable CA2225 // Operator overloads have named alternates - public static implicit operator BigInteger(ulong value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - return new BigInteger(value); - } - - /// - /// Defines an explicit conversion of a value to a value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator BigInteger(double value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - return new BigInteger(value); - } - - /// - /// Defines an explicit conversion of a object to a value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator BigInteger(float value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - return new BigInteger(value); - } - - /// - /// Defines an explicit conversion of a object to a value. - /// - /// The value to convert to a . - /// - /// An object that contains the value of the parameter. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static explicit operator BigInteger(decimal value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - return new BigInteger(value); - } - - /// - /// Adds the values of two specified objects. - /// - /// The first value to add. - /// The second value to add. - /// - /// The sum of and . - /// - public static BigInteger operator +(BigInteger left, BigInteger right) - { - if (left._sign == 0) - { - return right; - } - - if (right._sign == 0) - { - return left; - } - - if (left._sign == right._sign) - { - return new BigInteger(left._sign, CoreAdd(left._data, right._data)); - } - - var r = CoreCompare(left._data, right._data); - - if (r == 0) - { - return Zero; - } - - if (r > 0) - { - // left > right - return new BigInteger(left._sign, CoreSub(left._data, right._data)); - } - - return new BigInteger(right._sign, CoreSub(right._data, left._data)); - } - - /// - /// Subtracts a value from another value. - /// - /// The value to subtract from (the minuend). - /// The value to subtract (the subtrahend). - /// - /// The result of subtracting from . - /// - public static BigInteger operator -(BigInteger left, BigInteger right) - { - if (right._sign == 0) - { - return left; - } - - if (left._sign == 0) - { - return new BigInteger((short)-right._sign, right._data); - } - - if (left._sign == right._sign) - { - var r = CoreCompare(left._data, right._data); - - if (r == 0) - { - return Zero; - } - - if (r > 0) - { - // left > right - return new BigInteger(left._sign, CoreSub(left._data, right._data)); - } - - return new BigInteger((short)-right._sign, CoreSub(right._data, left._data)); - } - - return new BigInteger(left._sign, CoreAdd(left._data, right._data)); - } - - /// - /// Multiplies two specified values. - /// - /// The first value to multiply. - /// The second value to multiply. - /// - /// The product of left and right. - /// - public static BigInteger operator *(BigInteger left, BigInteger right) - { - if (left._sign == 0 || right._sign == 0) - { - return Zero; - } - - if (left._data[0] == 1 && left._data.Length == 1) - { - if (left._sign == 1) - { - return right; - } - - return new BigInteger((short)-right._sign, right._data); - } - - if (right._data[0] == 1 && right._data.Length == 1) - { - if (right._sign == 1) - { - return left; - } - - return new BigInteger((short)-left._sign, left._data); - } - - var a = left._data; - var b = right._data; - - var res = new uint[a.Length + b.Length]; - - for (var i = 0; i < a.Length; ++i) - { - var ai = a[i]; - var k = i; - - ulong carry = 0; - for (var j = 0; j < b.Length; ++j) - { - carry = carry + (((ulong)ai) * b[j]) + res[k]; - res[k++] = (uint)carry; - carry >>= 32; - } - - while (carry != 0) - { - carry += res[k]; - res[k++] = (uint)carry; - carry >>= 32; - } - } - - int m; - for (m = res.Length - 1; m >= 0 && res[m] == 0; --m) - { - // Intentionally empty block - } - - if (m < res.Length - 1) - { - Array.Resize(ref res, m + 1); - } - - return new BigInteger((short)(left._sign * right._sign), res); - } - - /// - /// Divides a specified value by another specified value by using - /// integer division. - /// - /// The value to be divided. - /// The value to divide by. - /// - /// The integral result of the division. - /// - public static BigInteger operator /(BigInteger dividend, BigInteger divisor) - { - if (divisor._sign == 0) - { - throw new DivideByZeroException(); - } - - if (dividend._sign == 0) - { - return dividend; - } - - DivModUnsigned(dividend._data, divisor._data, out var quotient, out _); - - int i; - for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i) - { - // Intentionally empty block - } - - if (i == -1) - { - return Zero; - } - - if (i < quotient.Length - 1) - { - Array.Resize(ref quotient, i + 1); - } - - return new BigInteger((short)(dividend._sign * divisor._sign), quotient); - } - - /// - /// Returns the remainder that results from division with two specified values. - /// - /// The value to be divided. - /// The value to divide by. - /// - /// The remainder that results from the division. - /// - public static BigInteger operator %(BigInteger dividend, BigInteger divisor) - { - if (divisor._sign == 0) - { - throw new DivideByZeroException(); - } - - if (dividend._sign == 0) - { - return dividend; - } - - DivModUnsigned(dividend._data, divisor._data, out _, out var remainderValue); - - int i; - for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i) - { - // Intentionally empty block - } - - if (i == -1) - { - return Zero; - } - - if (i < remainderValue.Length - 1) - { - Array.Resize(ref remainderValue, i + 1); - } - - return new BigInteger(dividend._sign, remainderValue); - } - - /// - /// Negates a specified value. - /// - /// The value to negate. - /// - /// The result of the parameter multiplied by negative one (-1). - /// - public static BigInteger operator -(BigInteger value) - { - if (value._data is null) - { - return value; - } - - return new BigInteger((short)-value._sign, value._data); - } - - /// - /// Returns the value of the operand. - /// - /// An integer value. - /// - /// The value of the operand. - /// - /// - /// The sign of the operand is unchanged. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static BigInteger operator +(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - return value; - } - - /// - /// Increments a value by 1. - /// - /// The value to increment. - /// - /// The value of the parameter incremented by 1. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static BigInteger operator ++(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (value._data is null) - { - return One; - } - - var sign = value._sign; - var data = value._data; - if (data.Length == 1) - { - if (sign == -1 && data[0] == 1) - { - return Zero; - } - - if (sign == 0) - { - return One; - } - } - - data = sign == -1 ? CoreSub(data, 1) : CoreAdd(data, 1); - - return new BigInteger(sign, data); - } - - /// - /// Decrements a value by 1. - /// - /// The value to decrement. - /// - /// The value of the parameter decremented by 1. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static BigInteger operator --(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (value._data is null) - { - return MinusOne; - } - - var sign = value._sign; - var data = value._data; - if (data.Length == 1) - { - if (sign == 1 && data[0] == 1) - { - return Zero; - } - - if (sign == 0) - { - return MinusOne; - } - } - - data = sign == -1 ? CoreAdd(data, 1) : CoreSub(data, 1); - - return new BigInteger(sign, data); - } - - /// - /// Performs a bitwise And operation on two values. - /// - /// The first value. - /// The second value. - /// - /// The result of the bitwise And operation. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static BigInteger operator &(BigInteger left, BigInteger right) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (left._sign == 0) - { - return left; - } - - if (right._sign == 0) - { - return right; - } - - var a = left._data; - var b = right._data; - int ls = left._sign; - int rs = right._sign; - - var negRes = (ls == rs) && (ls == -1); - - var result = new uint[Math.Max(a.Length, b.Length)]; - - ulong ac = 1, bc = 1, borrow = 1; - - int i; - for (i = 0; i < result.Length; ++i) - { - uint va = 0; - if (i < a.Length) - { - va = a[i]; - } - - if (ls == -1) - { - ac = ~va + ac; - va = (uint)ac; - ac = (uint)(ac >> 32); - } - - uint vb = 0; - if (i < b.Length) - { - vb = b[i]; - } - - if (rs == -1) - { - bc = ~vb + bc; - vb = (uint)bc; - bc = (uint)(bc >> 32); - } - - var word = va & vb; - - if (negRes) - { - borrow = word - borrow; - word = ~(uint)borrow; - borrow = (uint)(borrow >> 32) & 0x1u; - } - - result[i] = word; - } - - for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) - { - // Intentionally empty block - } - - if (i == -1) - { - return Zero; - } - - if (i < result.Length - 1) - { - Array.Resize(ref result, i + 1); - } - - return new BigInteger(negRes ? (short)-1 : (short)1, result); - } - - /// - /// Performs a bitwise Or operation on two values. - /// - /// The first value. - /// The second value. - /// - /// The result of the bitwise Or operation. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static BigInteger operator |(BigInteger left, BigInteger right) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (left._sign == 0) - { - return right; - } - - if (right._sign == 0) - { - return left; - } - - var a = left._data; - var b = right._data; - int ls = left._sign; - int rs = right._sign; - - var negRes = (ls == -1) || (rs == -1); - - var result = new uint[Math.Max(a.Length, b.Length)]; - - ulong ac = 1, bc = 1, borrow = 1; - - int i; - for (i = 0; i < result.Length; ++i) - { - uint va = 0; - if (i < a.Length) - { - va = a[i]; - } - - if (ls == -1) - { - ac = ~va + ac; - va = (uint)ac; - ac = (uint)(ac >> 32); - } - - uint vb = 0; - if (i < b.Length) - { - vb = b[i]; - } - - if (rs == -1) - { - bc = ~vb + bc; - vb = (uint)bc; - bc = (uint)(bc >> 32); - } - - var word = va | vb; - - if (negRes) - { - borrow = word - borrow; - word = ~(uint)borrow; - borrow = (uint)(borrow >> 32) & 0x1u; - } - - result[i] = word; - } - - for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) - { - // Intentionally empty block - } - - if (i == -1) - { - return Zero; - } - - if (i < result.Length - 1) - { - Array.Resize(ref result, i + 1); - } - - return new BigInteger(negRes ? (short)-1 : (short)1, result); - } - - /// - /// Performs a bitwise exclusive Or (XOr) operation on two values. - /// - /// The first value. - /// The second value. - /// - /// The result of the bitwise Or operation. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static BigInteger operator ^(BigInteger left, BigInteger right) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (left._sign == 0) - { - return right; - } - - if (right._sign == 0) - { - return left; - } - - var a = left._data; - var b = right._data; - int ls = left._sign; - int rs = right._sign; - - var negRes = (ls == -1) ^ (rs == -1); - - var result = new uint[Math.Max(a.Length, b.Length)]; - - ulong ac = 1, bc = 1, borrow = 1; - - int i; - for (i = 0; i < result.Length; ++i) - { - uint va = 0; - if (i < a.Length) - { - va = a[i]; - } - - if (ls == -1) - { - ac = ~va + ac; - va = (uint)ac; - ac = (uint)(ac >> 32); - } - - uint vb = 0; - if (i < b.Length) - { - vb = b[i]; - } - - if (rs == -1) - { - bc = ~vb + bc; - vb = (uint)bc; - bc = (uint)(bc >> 32); - } - - var word = va ^ vb; - - if (negRes) - { - borrow = word - borrow; - word = ~(uint)borrow; - borrow = (uint)(borrow >> 32) & 0x1u; - } - - result[i] = word; - } - - for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) - { - // Intentionally empty block - } - - if (i == -1) - { - return Zero; - } - - if (i < result.Length - 1) - { - Array.Resize(ref result, i + 1); - } - - return new BigInteger(negRes ? (short)-1 : (short)1, result); - } - - /// - /// Returns the bitwise one's complement of a value. - /// - /// An integer value. - /// - /// The bitwise one's complement of . - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static BigInteger operator ~(BigInteger value) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (value._data is null) - { - return MinusOne; - } - - var data = value._data; - int sign = value._sign; - - var negRes = sign == 1; - - var result = new uint[data.Length]; - - ulong carry = 1, borrow = 1; - - int i; - for (i = 0; i < result.Length; ++i) - { - var word = data[i]; - if (sign == -1) - { - carry = ~word + carry; - word = (uint)carry; - carry = (uint)(carry >> 32); - } - - word = ~word; - - if (negRes) - { - borrow = word - borrow; - word = ~(uint)borrow; - borrow = (uint)(borrow >> 32) & 0x1u; - } - - result[i] = word; - } - - for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) - { - // Intentionally empty block - } - - if (i == -1) - { - return Zero; - } - - if (i < result.Length - 1) - { - Array.Resize(ref result, i + 1); - } - - return new BigInteger(negRes ? (short)-1 : (short)1, result); - } - - /// - /// Returns the zero-based index of the most significant set bit. - /// - /// The value to scan. - /// - /// The zero-based index of the most significant set bit, or zero if no bit is set. - /// - private static int BitScanBackward(uint word) - { - for (var i = 31; i >= 0; --i) - { - var mask = 1u << i; - if ((word & mask) == mask) - { - return i; - } - } - - return 0; - } - - /// - /// Shifts a value a specified number of bits to the left. - /// - /// The value whose bits are to be shifted. - /// The number of bits to shift value to the left. - /// - /// A value that has been shifted to the left by the specified number of bits. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static BigInteger operator <<(BigInteger value, int shift) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (shift == 0 || value._data is null) - { - return value; - } - - if (shift < 0) - { - return value >> -shift; - } - - var data = value._data; - int sign = value._sign; - - var topMostIdx = BitScanBackward(data[data.Length - 1]); - var bits = shift - (31 - topMostIdx); - var extraWords = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0); - - var res = new uint[data.Length + extraWords]; - - var idxShift = shift >> 5; - var bitShift = shift & 0x1F; - var carryShift = 32 - bitShift; - - if (carryShift == 32) - { - for (var i = 0; i < data.Length; ++i) - { - var word = data[i]; - res[i + idxShift] |= word << bitShift; - } - } - else - { - for (var i = 0; i < data.Length; ++i) - { - var word = data[i]; - res[i + idxShift] |= word << bitShift; - if (i + idxShift + 1 < res.Length) - { - res[i + idxShift + 1] = word >> carryShift; - } - } - } - - return new BigInteger((short)sign, res); - } - - /// - /// Shifts a value a specified number of bits to the right. - /// - /// The value whose bits are to be shifted. - /// The number of bits to shift value to the right. - /// - /// A value that has been shifted to the right by the specified number of bits. - /// -#pragma warning disable CA2225 // Operator overloads have named alternates - public static BigInteger operator >>(BigInteger value, int shift) -#pragma warning restore CA2225 // Operator overloads have named alternates - { - if (shift == 0 || value._sign == 0) - { - return value; - } - - if (shift < 0) - { - return value << -shift; - } - - var data = value._data; - int sign = value._sign; - - var topMostIdx = BitScanBackward(data[data.Length - 1]); - var idxShift = shift >> 5; - var bitShift = shift & 0x1F; - - var extraWords = idxShift; - if (bitShift > topMostIdx) - { - ++extraWords; - } - - var size = data.Length - extraWords; - - if (size <= 0) - { - return sign == 1 ? Zero : MinusOne; - } - - var res = new uint[size]; - var carryShift = 32 - bitShift; - - if (carryShift == 32) - { - for (var i = data.Length - 1; i >= idxShift; --i) - { - var word = data[i]; - - if (i - idxShift < res.Length) - { - res[i - idxShift] |= word >> bitShift; - } - } - } - else - { - for (var i = data.Length - 1; i >= idxShift; --i) - { - var word = data[i]; - - if (i - idxShift < res.Length) - { - res[i - idxShift] |= word >> bitShift; - } - - if (i - idxShift - 1 >= 0) - { - res[i - idxShift - 1] = word << carryShift; - } - } - } - - // Round down instead of toward zero - if (sign == -1) - { - for (var i = 0; i < idxShift; i++) - { - if (data[i] != 0u) - { - var tmp = new BigInteger((short)sign, res); - --tmp; - return tmp; - } - } - - if (bitShift > 0 && (data[idxShift] << carryShift) != 0u) - { - var tmp = new BigInteger((short)sign, res); - --tmp; - return tmp; - } - } - - return new BigInteger((short)sign, res); - } - - /// - /// Returns a value that indicates whether a value is less than another - /// value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is less than ; otherwise, . - /// - public static bool operator <(BigInteger left, BigInteger right) - { - return Compare(left, right) < 0; - } - - /// - /// Returns a value that indicates whether a value is less than a 64-bit signed integer. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if left is than ; otherwise, . - /// - public static bool operator <(BigInteger left, long right) - { - return left.CompareTo(right) < 0; - } - - /// - /// Returns a value that indicates whether a 64-bit signed integer is less than a value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is less than ; - /// otherwise, . - /// - public static bool operator <(long left, BigInteger right) - { - return right.CompareTo(left) > 0; - } - - /// - /// Returns a value that indicates whether a 64-bit signed integer is less than a value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is less than ; otherwise, . - /// - [CLSCompliant(false)] - public static bool operator <(BigInteger left, ulong right) - { - return left.CompareTo(right) < 0; - } - - /// - /// Returns a value that indicates whether a 64-bit unsigned integer is less than a value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is less than ; otherwise, . - /// - [CLSCompliant(false)] - public static bool operator <(ulong left, BigInteger right) - { - return right.CompareTo(left) > 0; - } - - /// - /// Returns a value that indicates whether a value is less than or equal - /// to another value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is less than or equal to ; - /// otherwise, . - /// - public static bool operator <=(BigInteger left, BigInteger right) - { - return Compare(left, right) <= 0; - } - - /// - /// Returns a value that indicates whether a value is less than or equal - /// to a 64-bit signed integer. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is less than or equal to ; - /// otherwise, . - /// - public static bool operator <=(BigInteger left, long right) - { - return left.CompareTo(right) <= 0; - } - - /// - /// Returns a value that indicates whether a 64-bit signed integer is less than or equal to a value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is less than or equal to ; - /// otherwise, . - /// - public static bool operator <=(long left, BigInteger right) - { - return right.CompareTo(left) >= 0; - } - - /// - /// Returns a value that indicates whether a value is less than or equal to - /// a 64-bit unsigned integer. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is less than or equal to ; - /// otherwise, . - /// - [CLSCompliant(false)] - public static bool operator <=(BigInteger left, ulong right) - { - return left.CompareTo(right) <= 0; - } - - /// - /// Returns a value that indicates whether a 64-bit unsigned integer is less than or equal to a - /// value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is less than or equal to ; - /// otherwise, . - /// - [CLSCompliant(false)] - public static bool operator <=(ulong left, BigInteger right) - { - return right.CompareTo(left) >= 0; - } - - /// - /// Returns a value that indicates whether a value is greater than another - /// value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is greater than ; - /// otherwise, . - /// - public static bool operator >(BigInteger left, BigInteger right) - { - return Compare(left, right) > 0; - } - - /// - /// Returns a value that indicates whether a is greater than a 64-bit signed integer value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is greater than ; - /// otherwise, . - /// - public static bool operator >(BigInteger left, long right) - { - return left.CompareTo(right) > 0; - } - - /// - /// Returns a value that indicates whether a 64-bit signed integer is greater than a value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is greater than ; - /// otherwise, . - /// - public static bool operator >(long left, BigInteger right) - { - return right.CompareTo(left) < 0; - } - - /// - /// Returns a value that indicates whether a value is greater than a 64-bit unsigned integer. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is greater than ; - /// otherwise, . - /// - [CLSCompliant(false)] - public static bool operator >(BigInteger left, ulong right) - { - return left.CompareTo(right) > 0; - } - - /// - /// Returns a value that indicates whether a 64-bit unsigned integer is greater than a value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is greater than ; - /// otherwise, . - /// - [CLSCompliant(false)] - public static bool operator >(ulong left, BigInteger right) - { - return right.CompareTo(left) < 0; - } - - /// - /// Returns a value that indicates whether a value is greater than or equal - /// to another value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is greater than ; - /// otherwise, . - /// - public static bool operator >=(BigInteger left, BigInteger right) - { - return Compare(left, right) >= 0; - } - - /// - /// Returns a value that indicates whether a value is greater than or equal - /// to a 64-bit signed integer value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is greater than ; - /// otherwise, . - /// - public static bool operator >=(BigInteger left, long right) - { - return left.CompareTo(right) >= 0; - } - - /// - /// Returns a value that indicates whether a 64-bit signed integer is greater than or equal to a - /// value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is greater than ; - /// otherwise, . - /// - public static bool operator >=(long left, BigInteger right) - { - return right.CompareTo(left) <= 0; - } - - /// - /// Returns a value that indicates whether a value is greater than or equal to a - /// 64-bit unsigned integer value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is greater than ; - /// otherwise, . - /// - [CLSCompliant(false)] - public static bool operator >=(BigInteger left, ulong right) - { - return left.CompareTo(right) >= 0; - } - - /// - /// Returns a value that indicates whether a 64-bit unsigned integer is greater than or equal to a - /// value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if is greater than ; - /// otherwise, . - /// - [CLSCompliant(false)] - public static bool operator >=(ulong left, BigInteger right) - { - return right.CompareTo(left) <= 0; - } - - /// - /// Returns a value that indicates whether the values of two objects are equal. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if the and parameters have the same value; - /// otherwise, . - /// - public static bool operator ==(BigInteger left, BigInteger right) - { - return Compare(left, right) == 0; - } - - /// - /// Returns a value that indicates whether a value and a signed long integer value are equal. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if the and parameters have the same value; - /// otherwise, . - /// - public static bool operator ==(BigInteger left, long right) - { - return left.CompareTo(right) == 0; - } - - /// - /// Returns a value that indicates whether a signed long integer value and a value are equal. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if the and parameters have the same value; - /// otherwise, . - /// - public static bool operator ==(long left, BigInteger right) - { - return right.CompareTo(left) == 0; - } - - /// - /// Returns a value that indicates whether a value and an unsigned long integer value are equal. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if the and parameters have the same value; - /// otherwise, . - /// - [CLSCompliant(false)] - public static bool operator ==(BigInteger left, ulong right) - { - return left.CompareTo(right) == 0; - } - - /// - /// Returns a value that indicates whether an unsigned long integer value and a value are equal. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if the and parameters have the same value; - /// otherwise, . - /// - [CLSCompliant(false)] - public static bool operator ==(ulong left, BigInteger right) - { - return right.CompareTo(left) == 0; - } - - /// - /// Returns a value that indicates whether two objects have different values. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if and are not equal; - /// otherwise, . - /// - public static bool operator !=(BigInteger left, BigInteger right) - { - return Compare(left, right) != 0; - } - - /// - /// Returns a value that indicates whether a value and a 64-bit signed integer are not equal. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if and are not equal; - /// otherwise, . - /// - public static bool operator !=(BigInteger left, long right) - { - return left.CompareTo(right) != 0; - } - - /// - /// Returns a value that indicates whether a 64-bit signed integer and a value are not equal. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if and are not equal; - /// otherwise, . - /// - public static bool operator !=(long left, BigInteger right) - { - return right.CompareTo(left) != 0; - } - - /// - /// Returns a value that indicates whether a value and a 64-bit unsigned integer are not equal. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if and are not equal; - /// otherwise, . - /// - [CLSCompliant(false)] - public static bool operator !=(BigInteger left, ulong right) - { - return left.CompareTo(right) != 0; - } - - /// - /// Returns a value that indicates whether a 64-bit unsigned integer and a value are not equal. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// if and are not equal; - /// otherwise, . - /// - [CLSCompliant(false)] - public static bool operator !=(ulong left, BigInteger right) - { - return right.CompareTo(left) != 0; - } - - /// - /// Returns a value that indicates whether the current instance and a specified object have the same value. - /// - /// The object to compare. - /// - /// if the parameter is a object or a type capable - /// of implicit conversion to a value, and its value is equal to the value of the - /// current object; otherwise, . - /// - public override readonly bool Equals(object obj) - { - if (obj is not BigInteger other) - { - return false; - } - - return Equals(other); - } - - /// - /// Returns a value that indicates whether the current instance and a specified object - /// have the same value. - /// - /// The object to compare. - /// - /// if this object and have the same value; - /// otherwise, . - /// - public readonly bool Equals(BigInteger other) - { - if (_sign != other._sign) - { - return false; - } - - var alen = _data != null ? _data.Length : 0; - var blen = other._data != null ? other._data.Length : 0; - - if (alen != blen) - { - return false; - } - - for (var i = 0; i < alen; ++i) - { - if (_data[i] != other._data[i]) - { - return false; - } - } - - return true; - } - - /// - /// Returns a value that indicates whether the current instance and a signed 64-bit integer have the same value. - /// - /// The signed 64-bit integer value to compare. - /// - /// if the signed 64-bit integer and the current instance have the same value; otherwise, . - /// - public readonly bool Equals(long other) - { - return CompareTo(other) == 0; - } - - /// - /// Returns a value that indicates whether the current instance and an unsigned 64-bit integer have the same value. - /// - /// The unsigned 64-bit integer to compare. - /// - /// if the current instance and the unsigned 64-bit integer have the same value; otherwise, . - /// - [CLSCompliant(false)] - public readonly bool Equals(ulong other) - { - return CompareTo(other) == 0; - } - - /// - /// Converts the numeric value of the current object to its equivalent string representation. - /// - /// - /// The string representation of the current value. - /// - public override readonly string ToString() - { - return ToString(10, provider: null); - } - - /// - /// Converts the numeric value of the current object to its equivalent string representation - /// by using the specified format. - /// - /// A standard or custom numeric format string. - /// - /// The string representation of the current value in the format specified by the - /// parameter. - /// - /// is not a valid format string. - public readonly string ToString(string format) - { - return ToString(format, formatProvider: null); - } - - /// - /// Converts the numeric value of the current object to its equivalent string representation - /// by using the specified culture-specific formatting information. - /// - /// An object that supplies culture-specific formatting information. - /// - /// The string representation of the current value in the format specified by the - /// parameter. - /// - public readonly string ToString(IFormatProvider provider) - { - return ToString(format: null, provider); - } - - /// - /// Converts the numeric value of the current object to its equivalent string representation - /// by using the specified format and culture-specific format information. - /// - /// A standard or custom numeric format string. - /// An object that supplies culture-specific formatting information. - /// - /// The string representation of the current value as specified by the - /// and parameters. - /// - public readonly string ToString(string format, IFormatProvider formatProvider) - { - if (string.IsNullOrEmpty(format)) - { - return ToString(10, formatProvider); - } - - switch (format[0]) - { - case 'd': - case 'D': - case 'g': - case 'G': - case 'r': - case 'R': - return ToStringWithPadding(format, 10, formatProvider); - case 'x': - case 'X': - return ToStringWithPadding(format, 16, provider: null); - default: - throw new FormatException(string.Format("format '{0}' not implemented", format)); - } - } - - private readonly string ToStringWithPadding(string format, uint radix, IFormatProvider provider) - { - if (format.Length > 1) - { - var precision = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat); - var baseStr = ToString(radix, provider); - if (baseStr.Length < precision) - { - var additional = new string('0', precision - baseStr.Length); - if (baseStr[0] != '-') - { - return additional + baseStr; - } - -#if NET - return string.Concat("-", additional, baseStr.AsSpan(1)); -#else - return "-" + additional + baseStr.Substring(1); -#endif // NET - } - - return baseStr; - } - - return ToString(radix, provider); - } - - private static uint[] MakeTwoComplement(uint[] v) - { - var res = new uint[v.Length]; - - ulong carry = 1; - for (var i = 0; i < v.Length; ++i) - { - var word = v[i]; - carry = (ulong)~word + carry; - word = (uint)carry; - carry = (uint)(carry >> 32); - res[i] = word; - } - - var last = res[res.Length - 1]; - var idx = FirstNonFfByte(last); - uint mask = 0xFF; - for (var i = 1; i < idx; ++i) - { - mask = (mask << 8) | 0xFF; - } - - res[res.Length - 1] = last & mask; - return res; - } - - private readonly string ToString(uint radix, IFormatProvider provider) - { - const string characterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - if (characterSet.Length < radix) - { - throw new ArgumentException("charSet length less than radix", nameof(radix)); - } - - if (radix == 1) - { - throw new ArgumentException("There is no such thing as radix one notation", nameof(radix)); - } - - if (_sign == 0) - { - return "0"; - } - - if (_data.Length == 1 && _data[0] == 1) - { - return _sign == 1 ? "1" : "-1"; - } - - var digits = new List(1 + ((_data.Length * 3) / 10)); - - BigInteger a; - if (_sign == 1) - { - a = this; - } - else - { - var dt = _data; - if (radix > 10) - { - dt = MakeTwoComplement(dt); - } - - a = new BigInteger(1, dt); - } - - while (a != 0) - { - a = DivRem(a, radix, out var rem); - digits.Add(characterSet[(int)rem]); - } - - if (_sign == -1 && radix == 10) - { - NumberFormatInfo info = null; - if (provider != null) - { - info = provider.GetFormat(typeof(NumberFormatInfo)) as NumberFormatInfo; - } - - if (info != null) - { - var str = info.NegativeSign; - for (var i = str.Length - 1; i >= 0; --i) - { - digits.Add(str[i]); - } - } - else - { - digits.Add('-'); - } - } - - var last = digits[digits.Count - 1]; - if (_sign == 1 && radix > 10 && (last < '0' || last > '9')) - { - digits.Add('0'); - } - - digits.Reverse(); - - return new string(digits.ToArray()); - } - - /// - /// Converts the string representation of a number to its equivalent. - /// - /// A string that contains the number to convert. - /// - /// A value that is equivalent to the number specified in the parameter. - /// - /// is . - /// is not in the correct format. - public static BigInteger Parse(string value) - { - if (!Parse(value, tryParse: false, out var result, out var ex)) - { - throw ex; - } - - return result; - } - - /// - /// Converts the string representation of a number in a specified style to its equivalent. - /// - /// A string that contains a number to convert. - /// A bitwise combination of the enumeration values that specify the permitted format of . - /// - /// A value that is equivalent to the number specified in the parameter. - /// - /// - /// is not a value. - /// -or- - /// includes the or flag along with another value. - /// - /// is . - /// does not comply with the input pattern specified by . - public static BigInteger Parse(string value, NumberStyles style) - { - return Parse(value, style, provider: null); - } - - /// - /// Converts the string representation of a number in a specified style to its equivalent. - /// - /// A string that contains a number to convert. - /// An object that provides culture-specific formatting information about . - /// - /// A value that is equivalent to the number specified in the parameter. - /// - /// is . - /// is not in the correct format. - public static BigInteger Parse(string value, IFormatProvider provider) - { - return Parse(value, NumberStyles.Integer, provider); - } - - /// - /// Converts the string representation of a number in a specified style and culture-specific format to its equivalent. - /// - /// A string that contains a number to convert. - /// A bitwise combination of the enumeration values that specify the permitted format of . - /// An object that provides culture-specific formatting information about . - /// - /// A value that is equivalent to the number specified in the parameter. - /// - /// - /// is not a value. - /// -or- - /// includes the or flag along with another value. - /// - /// is . - /// does not comply with the input pattern specified by . - public static BigInteger Parse(string value, NumberStyles style, IFormatProvider provider) - { - if (!Parse(value, style, provider, tryParse: false, out var res, out var exc)) - { - throw exc; - } - - return res; - } - - /// - /// Tries to convert the string representation of a number to its equivalent, and - /// returns a value that indicates whether the conversion succeeded. - /// - /// The string representation of a number. - /// When this method returns, contains the equivalent to the number that is contained in value, or zero (0) if the conversion fails. The conversion fails if the parameter is or is not of the correct format. This parameter is passed uninitialized. - /// - /// if was converted successfully; otherwise, . - /// - /// is . - public static bool TryParse(string value, out BigInteger result) - { - return Parse(value, tryParse: true, out result, out _); - } - - /// - /// Tries to convert the string representation of a number in a specified style and culture-specific format to its - /// equivalent, and returns a value that indicates whether the conversion succeeded. - /// - /// The string representation of a number. - /// A bitwise combination of enumeration values that indicates the style elements that can be present in . - /// An object that supplies culture-specific formatting information about . - /// When this method returns, contains the equivalent to the number that is contained in value, or if the conversion fails. The conversion fails if the parameter is or is not of the correct format. This parameter is passed uninitialized. - /// - /// if was converted successfully; otherwise, . - /// - /// - /// is not a value. - /// -or- - /// includes the or flag along with another value. - /// - public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out BigInteger result) - { - if (!Parse(value, style, provider, tryParse: true, out result, out _)) - { - result = Zero; - return false; - } - - return true; - } - -#pragma warning disable S4136 // Method overloads should be grouped together - private static bool Parse(string value, NumberStyles style, IFormatProvider fp, bool tryParse, out BigInteger result, out Exception exc) -#pragma warning restore S4136 // Method overloads should be grouped together - { - result = Zero; - exc = null; - - if (value is null) - { - if (!tryParse) - { - exc = new ArgumentNullException(nameof(value)); - } - - return false; - } - - if (value.Length == 0) - { - if (!tryParse) - { - exc = GetFormatException(); - } - - return false; - } - - NumberFormatInfo nfi = null; - if (fp != null) - { - var typeNfi = typeof(NumberFormatInfo); - nfi = (NumberFormatInfo)fp.GetFormat(typeNfi); - } - - nfi ??= NumberFormatInfo.CurrentInfo; - - if (!CheckStyle(style, tryParse, ref exc)) - { - return false; - } - - var allowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) == NumberStyles.AllowCurrencySymbol; - var allowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) == NumberStyles.AllowHexSpecifier; - var allowThousands = (style & NumberStyles.AllowThousands) == NumberStyles.AllowThousands; - var allowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) == NumberStyles.AllowDecimalPoint; - var allowParentheses = (style & NumberStyles.AllowParentheses) == NumberStyles.AllowParentheses; - var allowTrailingSign = (style & NumberStyles.AllowTrailingSign) == NumberStyles.AllowTrailingSign; - var allowLeadingSign = (style & NumberStyles.AllowLeadingSign) == NumberStyles.AllowLeadingSign; - var allowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) == NumberStyles.AllowTrailingWhite; - var allowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) == NumberStyles.AllowLeadingWhite; - var allowExponent = (style & NumberStyles.AllowExponent) == NumberStyles.AllowExponent; - - var pos = 0; - - if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) - { - return false; - } - - var foundOpenParentheses = false; - var negative = false; - var foundSign = false; - var foundCurrency = false; - - // Pre-number stuff - if (allowParentheses && value[pos] == '(') - { - foundOpenParentheses = true; - foundSign = true; - negative = true; // MS always make the number negative when there parentheses, even when NumberFormatInfo.NumberNegativePattern != 0 - pos++; - - if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) - { - return false; - } - - if (value.Substring(pos, nfi.NegativeSign.Length) == nfi.NegativeSign) - { - if (!tryParse) - { - exc = GetFormatException(); - } - - return false; - } - - if (value.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign) - { - if (!tryParse) - { - exc = GetFormatException(); - } - - return false; - } - } - - if (allowLeadingSign && !foundSign) - { - // Sign + Currency - FindSign(ref pos, value, nfi, ref foundSign, ref negative); - if (foundSign) - { - if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) - { - return false; - } - - if (allowCurrencySymbol) - { - FindCurrency(ref pos, value, nfi, ref foundCurrency); - if (foundCurrency && allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) - { - return false; - } - } - } - } - - if (allowCurrencySymbol && !foundCurrency) - { - // Currency + sign - FindCurrency(ref pos, value, nfi, ref foundCurrency); - if (foundCurrency) - { - if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) - { - return false; - } - - if (foundCurrency) - { - if (!foundSign && allowLeadingSign) - { - FindSign(ref pos, value, nfi, ref foundSign, ref negative); - if (foundSign && allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) - { - return false; - } - } - } - } - } - - var number = Zero; - var nDigits = 0; - var decimalPointPos = -1; - var firstHexDigit = true; - - // Number stuff - while (pos < value.Length) - { - if (!ValidDigit(value[pos], allowHexSpecifier)) - { - if (allowThousands && - (FindOther(ref pos, value, nfi.NumberGroupSeparator) - || FindOther(ref pos, value, nfi.CurrencyGroupSeparator))) - { - continue; - } - - if (allowDecimalPoint && decimalPointPos < 0 && - (FindOther(ref pos, value, nfi.NumberDecimalSeparator) - || FindOther(ref pos, value, nfi.CurrencyDecimalSeparator))) - { - decimalPointPos = nDigits; - continue; - } - - break; - } - - nDigits++; - - if (allowHexSpecifier) - { - var hexDigit = value[pos++]; - byte digitValue; - if (char.IsDigit(hexDigit)) - { - digitValue = (byte)(hexDigit - '0'); - } - else if (char.IsLower(hexDigit)) - { - digitValue = (byte)(hexDigit - 'a' + 10); - } - else - { - digitValue = (byte)(hexDigit - 'A' + 10); - } - - if (firstHexDigit && digitValue >= 8) - { - negative = true; - } - - number = (number * 16) + digitValue; - firstHexDigit = false; - continue; - } - - number = (number * 10) + (byte)(value[pos++] - '0'); - } - - // Post number stuff - if (nDigits == 0) - { - if (!tryParse) - { - exc = GetFormatException(); - } - - return false; - } - - // Signed hex value (Two's Complement) - if (allowHexSpecifier && negative) - { - var mask = Pow(16, nDigits) - 1; - number = (number ^ mask) + 1; - } - - var exponent = 0; - if (allowExponent) - { - if (FindExponent(ref pos, value, ref exponent, tryParse, ref exc) && exc != null) - { - return false; - } - } - - if (allowTrailingSign && !foundSign) - { - // Sign + Currency - FindSign(ref pos, value, nfi, ref foundSign, ref negative); - if (foundSign && pos < value.Length) - { - if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) - { - return false; - } - } - } - - if (allowCurrencySymbol && !foundCurrency) - { - if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, reportError: false, tryParse, ref exc)) - { - return false; - } - - // Currency + sign - FindCurrency(ref pos, value, nfi, ref foundCurrency); - if (foundCurrency && pos < value.Length) - { - if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) - { - return false; - } - - if (!foundSign && allowTrailingSign) - { - FindSign(ref pos, value, nfi, ref foundSign, ref negative); - } - } - } - - if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, reportError: false, tryParse, ref exc)) - { - return false; - } - - if (foundOpenParentheses) - { - if (pos >= value.Length || value[pos++] != ')') - { - if (!tryParse) - { - exc = GetFormatException(); - } - - return false; - } - - if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, reportError: false, tryParse, ref exc)) - { - return false; - } - } - - if (pos < value.Length && value[pos] != '\u0000') - { - if (!tryParse) - { - exc = GetFormatException(); - } - - return false; - } - - if (decimalPointPos >= 0) - { - exponent = exponent - nDigits + decimalPointPos; - } - - if (exponent < 0) - { - // Any non-zero values after decimal point are not allowed - number = DivRem(number, Pow(10, -exponent), out var remainder); - - if (!remainder.IsZero) - { - if (!tryParse) - { - exc = new OverflowException(string.Format(CultureInfo.InvariantCulture, - "Value too large or too small. exp= {0} rem = {1} pow = {2}", - exponent, - remainder, - Pow(10, -exponent))); - } - - return false; - } - } - else if (exponent > 0) - { - number = Pow(10, exponent) * number; - } - - if (number._sign == 0) - { - result = number; - } - else if (negative) - { - result = new BigInteger(-1, number._data); - } - else - { - result = new BigInteger(1, number._data); - } - - return true; - } - - private static bool CheckStyle(NumberStyles style, bool tryParse, ref Exception exc) - { - if ((style & NumberStyles.AllowHexSpecifier) == NumberStyles.AllowHexSpecifier) - { - var ne = style ^ NumberStyles.AllowHexSpecifier; - if ((ne & NumberStyles.AllowLeadingWhite) == NumberStyles.AllowLeadingWhite) - { - ne ^= NumberStyles.AllowLeadingWhite; - } - - if ((ne & NumberStyles.AllowTrailingWhite) == NumberStyles.AllowTrailingWhite) - { - ne ^= NumberStyles.AllowTrailingWhite; - } - - if (ne != NumberStyles.None) - { - if (!tryParse) - { - exc = new ArgumentException("With AllowHexSpecifier only " + - "AllowLeadingWhite and AllowTrailingWhite " + - "are permitted."); - } - - return false; - } - } - else if ((uint)style > (uint)NumberStyles.Any) - { - if (!tryParse) - { - exc = new ArgumentException("Not a valid number style"); - } - - return false; - } - - return true; - } - - private static bool JumpOverWhitespace(ref int pos, string s, bool reportError, bool tryParse, ref Exception exc) - { - while (pos < s.Length && char.IsWhiteSpace(s[pos])) - { - pos++; - } - - if (reportError && pos >= s.Length) - { - if (!tryParse) - { - exc = GetFormatException(); - } - - return false; - } - - return true; - } - - private static void FindSign(ref int pos, string s, NumberFormatInfo nfi, ref bool foundSign, ref bool negative) - { - if ((pos + nfi.NegativeSign.Length) <= s.Length && - string.CompareOrdinal(s, pos, nfi.NegativeSign, 0, nfi.NegativeSign.Length) == 0) - { - negative = true; - foundSign = true; - pos += nfi.NegativeSign.Length; - } - else if ((pos + nfi.PositiveSign.Length) <= s.Length && - string.CompareOrdinal(s, pos, nfi.PositiveSign, 0, nfi.PositiveSign.Length) == 0) - { - negative = false; - pos += nfi.PositiveSign.Length; - foundSign = true; - } - } - - private static void FindCurrency(ref int pos, string s, NumberFormatInfo nfi, ref bool foundCurrency) - { - if ((pos + nfi.CurrencySymbol.Length) <= s.Length && - s.Substring(pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol) - { - foundCurrency = true; - pos += nfi.CurrencySymbol.Length; - } - } - - private static bool FindExponent(ref int pos, string s, ref int exponent, bool tryParse, ref Exception exc) - { - exponent = 0; - - if (pos >= s.Length || (s[pos] != 'e' && s[pos] != 'E')) - { - exc = null; - return false; - } - - var i = pos + 1; - if (i == s.Length) - { - exc = tryParse ? null : GetFormatException(); - return true; - } - - var negative = false; - if (s[i] == '-') - { - negative = true; - if (++i == s.Length) - { - exc = tryParse ? null : GetFormatException(); - return true; - } - } - - if (s[i] == '+' && ++i == s.Length) - { - exc = tryParse ? null : GetFormatException(); - return true; - } - - long exp = 0; // temp long value - for (; i < s.Length; i++) - { - if (!char.IsDigit(s[i])) - { - exc = tryParse ? null : GetFormatException(); - return true; - } - - // Reduce the risk of throwing an overflow exc - exp = checked((exp * 10) - (s[i] - '0')); - if (exp is < int.MinValue or > int.MaxValue) - { - exc = tryParse ? null : new OverflowException("Value too large or too small."); - return true; - } - } - - // exp value saved as negative - if (!negative) - { - exp = -exp; - } - - exc = null; - exponent = (int)exp; - pos = i; - return true; - } - - private static bool FindOther(ref int pos, string s, string other) - { - if ((pos + other.Length) <= s.Length && - s.Substring(pos, other.Length) == other) - { - pos += other.Length; - return true; - } - - return false; - } - - private static bool ValidDigit(char e, bool allowHex) - { - if (allowHex) - { - return char.IsDigit(e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f'); - } - - return char.IsDigit(e); - } - - private static FormatException GetFormatException() - { - return new FormatException("Input string was not in the correct format"); - } - - private static bool ProcessTrailingWhitespace(bool tryParse, string s, int position, ref Exception exc) - { - var len = s.Length; - - for (var i = position; i < len; i++) - { - var c = s[i]; - - if (c != 0 && !char.IsWhiteSpace(c)) - { - if (!tryParse) - { - exc = GetFormatException(); - } - - return false; - } - } - - return true; - } - - private static bool Parse(string value, bool tryParse, out BigInteger result, out Exception exc) - { - int i, sign = 1; - var digitsSeen = false; - - result = Zero; - exc = null; - - if (value is null) - { - if (!tryParse) - { - exc = new ArgumentNullException(nameof(value)); - } - - return false; - } - - var len = value.Length; - - char c; - for (i = 0; i < len; i++) - { - c = value[i]; - if (!char.IsWhiteSpace(c)) - { - break; - } - } - - if (i == len) - { - if (!tryParse) - { - exc = GetFormatException(); - } - - return false; - } - - var info = NumberFormatInfo.CurrentInfo; - - var negative = info.NegativeSign; - var positive = info.PositiveSign; - - if (string.CompareOrdinal(value, i, positive, 0, positive.Length) == 0) - { - i += positive.Length; - } - else if (string.CompareOrdinal(value, i, negative, 0, negative.Length) == 0) - { - sign = -1; - i += negative.Length; - } - - var val = Zero; - for (; i < len; i++) - { - c = value[i]; - - if (c == '\0') - { - i = len; - continue; - } - - if (c is >= '0' and <= '9') - { - var d = (byte)(c - '0'); - - val = (val * 10) + d; - - digitsSeen = true; - } - else if (!ProcessTrailingWhitespace(tryParse, value, i, ref exc)) - { - return false; - } - } - - if (!digitsSeen) - { - if (!tryParse) - { - exc = GetFormatException(); - } - - return false; - } - - if (val._sign == 0) - { - result = val; - } -#pragma warning disable CA1508 // Avoid dead conditional code | this is the following bug in the analyzer rule: https://github.com/dotnet/roslyn-analyzers/issues/6991 - else if (sign == -1) -#pragma warning restore CA1508 // Avoid dead conditional code - { - result = new BigInteger(-1, val._data); - } - else - { - result = new BigInteger(1, val._data); - } - - return true; - } - - /// - /// Returns the smaller of two values. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// The or parameter, whichever is smaller. - /// - public static BigInteger Min(BigInteger left, BigInteger right) - { - int ls = left._sign; - int rs = right._sign; - - if (ls < rs) - { - return left; - } - - if (rs < ls) - { - return right; - } - - var r = CoreCompare(left._data, right._data); - if (ls == -1) - { - r = -r; - } - - if (r <= 0) - { - return left; - } - - return right; - } - - /// - /// Returns the larger of two values. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// The or parameter, whichever is larger. - /// - public static BigInteger Max(BigInteger left, BigInteger right) - { - int ls = left._sign; - int rs = right._sign; - - if (ls > rs) - { - return left; - } - - if (rs > ls) - { - return right; - } - - var r = CoreCompare(left._data, right._data); - if (ls == -1) - { - r = -r; - } - - if (r >= 0) - { - return left; - } - - return right; - } - - /// - /// Gets the absolute value of a object. - /// - /// A number. - /// - /// The absolute value of . - /// - public static BigInteger Abs(BigInteger value) - { - return new BigInteger(Math.Abs(value._sign), value._data); - } - - /// - /// Divides one value by another, returns the result, and returns the remainder in - /// an output parameter. - /// - /// The value to be divided. - /// The value to divide by. - /// When this method returns, contains a value that represents the remainder from the division. This parameter is passed uninitialized. - /// - /// The quotient of the division. - /// - public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder) - { - if (divisor._sign == 0) - { - throw new DivideByZeroException(); - } - - if (dividend._sign == 0) - { - remainder = dividend; - return dividend; - } - - DivModUnsigned(dividend._data, divisor._data, out var quotient, out var remainderValue); - - int i; - for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i) - { - // Intentionally empty block - } - - if (i == -1) - { - remainder = Zero; - } - else - { - if (i < remainderValue.Length - 1) - { - Array.Resize(ref remainderValue, i + 1); - } - - remainder = new BigInteger(dividend._sign, remainderValue); - } - - for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i) - { - // Intentionally empty block - } - - if (i == -1) - { - return Zero; - } - - if (i < quotient.Length - 1) - { - Array.Resize(ref quotient, i + 1); - } - - return new BigInteger((short)(dividend._sign * divisor._sign), quotient); - } - - /// - /// Raises a value to the power of a specified value. - /// - /// The number to raise to the power. - /// The exponent to raise by. - /// - /// The result of raising to the power. - /// - public static BigInteger Pow(BigInteger value, int exponent) - { - if (exponent < 0) - { - throw new ArgumentOutOfRangeException(nameof(exponent), "exp must be >= 0"); - } - - if (exponent == 0) - { - return One; - } - - if (exponent == 1) - { - return value; - } - - var result = One; - while (exponent != 0) - { - if ((exponent & 1) != 0) - { - result *= value; - } - - if (exponent == 1) - { - break; - } - - value *= value; - exponent >>= 1; - } - - return result; - } - - /// - /// Performs modulus division on a number raised to the power of another number. - /// - /// The number to raise to the power. - /// The exponent to raise by. - /// The number by which to divide raised to the power. - /// - /// The remainder after dividing raised by by - /// . - /// - /// is negative. - public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigInteger modulus) - { - if (exponent._sign == -1) - { - throw new ArgumentOutOfRangeException(nameof(exponent), "power must be >= 0"); - } - - if (modulus._sign == 0) - { - throw new DivideByZeroException(); - } - - var result = One % modulus; - while (exponent._sign != 0) - { - if (!exponent.IsEven) - { - result *= value; - result %= modulus; - } - - if (exponent.IsOne) - { - break; - } - - value *= value; - value %= modulus; - exponent >>= 1; - } - - return result; - } - - /// - /// Finds the greatest common divisor of two values. - /// - /// The first value. - /// The second value. - /// - /// The greatest common divisor of and . - /// - public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right) - { - if (left._sign != 0 && left._data.Length == 1 && left._data[0] == 1) - { - return One; - } - - if (right._sign != 0 && right._data.Length == 1 && right._data[0] == 1) - { - return One; - } - - if (left.IsZero) - { - return Abs(right); - } - - if (right.IsZero) - { - return Abs(left); - } - - var x = new BigInteger(1, left._data); - var y = new BigInteger(1, right._data); - - var g = y; - - while (x._data.Length > 1) - { - g = x; - x = y % x; - y = g; - } - - if (x.IsZero) - { - return g; - } - - // TODO: should we have something here if we can convert to long? - - /* - * Now we can just do it with single precision. I am using the binary gcd method, - * as it should be faster. - */ - - var yy = x._data[0]; - var xx = (uint)(y % yy); - - var t = 0; - - while (((xx | yy) & 1) == 0) - { - xx >>= 1; - yy >>= 1; - t++; - } - - while (xx != 0) - { - while ((xx & 1) == 0) - { - xx >>= 1; - } - - while ((yy & 1) == 0) - { - yy >>= 1; - } - - if (xx >= yy) - { - xx = (xx - yy) >> 1; - } - else - { - yy = (yy - xx) >> 1; - } - } - - return yy << t; - } - - /* - * LAMESPEC Log doesn't specify to how many ulp is has to be precise - * We are equilavent to MS with about 2 ULP - */ - - /// - /// Returns the logarithm of a specified number in a specified base. - /// - /// A number whose logarithm is to be found. - /// The base of the logarithm. - /// - /// The base logarithm of value. - /// - /// The log of is out of range of the data type. - public static double Log(BigInteger value, double baseValue) - { - if (value._sign == -1 || baseValue == 1.0d || baseValue == -1.0d || - baseValue == double.NegativeInfinity || double.IsNaN(baseValue)) - { - return double.NaN; - } - - if (baseValue is 0.0d or double.PositiveInfinity) - { - return value.IsOne ? 0 : double.NaN; - } - - if (value._data is null) - { - return double.NegativeInfinity; - } - - var length = value._data.Length - 1; - var bitCount = -1; - for (var curBit = 31; curBit >= 0; curBit--) - { - if ((value._data[length] & (1 << curBit)) != 0) - { - bitCount = curBit + (length * 32); - break; - } - } - - long bitlen = bitCount; - double c = 0, d = 1; - - var testBit = One; - var tempBitlen = bitlen; - while (tempBitlen > int.MaxValue) - { - testBit <<= int.MaxValue; - tempBitlen -= int.MaxValue; - } - - testBit <<= (int)tempBitlen; - - for (var curbit = bitlen; curbit >= 0; --curbit) - { - if ((value & testBit)._sign != 0) - { - c += d; - } - - d *= 0.5; - testBit >>= 1; - } - - return (Math.Log(c) + (Math.Log(2) * bitlen)) / Math.Log(baseValue); - } - - /// - /// Returns the natural (base e) logarithm of a specified number. - /// - /// The number whose logarithm is to be found. - /// - /// The natural (base e) logarithm of . - /// - /// The base 10 log of value is out of range of the data type. - public static double Log(BigInteger value) - { - return Log(value, Math.E); - } - - /// - /// Returns the base 10 logarithm of a specified number. - /// - /// A number whose logarithm is to be found. - /// - /// The base 10 logarithm of . - /// - /// The base 10 log of value is out of range of the data type. - public static double Log10(BigInteger value) - { - return Log(value, 10); - } - - /// - /// Returns the hash code for the current object. - /// - /// - /// A 32-bit signed integer hash code. - /// - public override readonly int GetHashCode() - { - var hash = (uint)(_sign * 0x01010101u); - if (_data != null) - { - foreach (var bit in _data) - { - hash ^= bit; - } - } - - return (int)hash; - } - - /// - /// Adds two values and returns the result. - /// - /// The first value to add. - /// The second value to add. - /// - /// The sum of and . - /// - public static BigInteger Add(BigInteger left, BigInteger right) - { - return left + right; - } - - /// - /// Subtracts one value from another and returns the result. - /// - /// The value to subtract from (the minuend). - /// The value to subtract (the subtrahend). - /// - /// The result of subtracting from . - /// - public static BigInteger Subtract(BigInteger left, BigInteger right) - { - return left - right; - } - - /// - /// Returns the product of two values. - /// - /// The first number to multiply. - /// The second number to multiply. - /// - /// The product of the and parameters. - /// - public static BigInteger Multiply(BigInteger left, BigInteger right) - { - return left * right; - } - - /// - /// Divides one value by another and returns the result. - /// - /// The value to be divided. - /// The value to divide by. - /// - /// The quotient of the division. - /// - public static BigInteger Divide(BigInteger dividend, BigInteger divisor) - { - return dividend / divisor; - } - - /// - /// Performs integer division on two values and returns the remainder. - /// - /// The value to be divided. - /// The value to divide by. - /// - /// The remainder after dividing by . - /// - public static BigInteger Remainder(BigInteger dividend, BigInteger divisor) - { - return dividend % divisor; - } - - /// - /// Negates a specified value. - /// - /// The value to negate. - /// - /// The result of the parameter multiplied by negative one (-1). - /// - public static BigInteger Negate(BigInteger value) - { - return -value; - } - - /// - /// Compares this instance to a specified object and returns an integer that indicates whether the value of - /// this instance is less than, equal to, or greater than the value of the specified object. - /// - /// The object to compare. - /// - /// A signed integer that indicates the relationship of the current instance to the parameter, - /// as shown in the following table. - /// - /// - /// Value - /// Condition - /// - /// - /// Less than zero - /// The current instance is less than . - /// - /// - /// Zero - /// The current instance equals . - /// - /// - /// Greater than zero - /// The current instance is greater than . - /// - /// - /// - /// is not a . - public readonly int CompareTo(object obj) - { - if (obj is null) - { - return 1; - } - - if (obj is not BigInteger other) - { - return -1; - } - - return Compare(this, other); - } - - /// - /// Compares this instance to a second and returns an integer that indicates whether the - /// value of this instance is less than, equal to, or greater than the value of the specified object. - /// - /// The object to compare. - /// - /// A signed integer value that indicates the relationship of this instance to , as - /// shown in the following table. - /// - /// - /// Value - /// Condition - /// - /// - /// Less than zero - /// The current instance is less than . - /// - /// - /// Zero - /// The current instance equals . - /// - /// - /// Greater than zero - /// The current instance is greater than . - /// - /// - /// - public readonly int CompareTo(BigInteger other) - { - return Compare(this, other); - } - - /// - /// Compares this instance to an unsigned 64-bit integer and returns an integer that indicates whether the value of this - /// instance is less than, equal to, or greater than the value of the unsigned 64-bit integer. - /// - /// The unsigned 64-bit integer to compare. - /// - /// A signed integer that indicates the relative value of this instance and , as shown - /// in the following table. - /// - /// - /// Value - /// Condition - /// - /// - /// Less than zero - /// The current instance is less than . - /// - /// - /// Zero - /// The current instance equals . - /// - /// - /// Greater than zero - /// The current instance is greater than . - /// - /// - /// - [CLSCompliant(false)] - public readonly int CompareTo(ulong other) - { - if (_sign < 0) - { - return -1; - } - - if (_sign == 0) - { - return other == 0 ? 0 : -1; - } - - if (_data.Length > 2) - { - return 1; - } - - var high = (uint)(other >> 32); - var low = (uint)other; - - return LongCompare(low, high); - } - - /// - /// Compares this instance to a signed 64-bit integer and returns an integer that indicates whether the value of this - /// instance is less than, equal to, or greater than the value of the signed 64-bit integer. - /// - /// The signed 64-bit integer to compare. - /// - /// A signed integer that indicates the relative value of this instance and , as shown - /// in the following table. - /// - /// - /// Value - /// Condition - /// - /// - /// Less than zero - /// The current instance is less than . - /// - /// - /// Zero - /// The current instance equals . - /// - /// - /// Greater than zero - /// The current instance is greater than . - /// - /// - /// - public readonly int CompareTo(long other) - { - int ls = _sign; - var rs = Math.Sign(other); - - if (ls != rs) - { - return ls > rs ? 1 : -1; - } - - if (ls == 0) - { - return 0; - } - - if (_data.Length > 2) - { - return _sign; - } - - if (other < 0) - { - other = -other; - } - - var low = (uint)other; - var high = (uint)((ulong)other >> 32); - - var r = LongCompare(low, high); - if (ls == -1) - { - r = -r; - } - - return r; - } - - private readonly int LongCompare(uint low, uint high) - { - uint h = 0; - - if (_data.Length > 1) - { - h = _data[1]; - } - - if (h > high) - { - return 1; - } - - if (h < high) - { - return -1; - } - - var l = _data[0]; - - if (l > low) - { - return 1; - } - - if (l < low) - { - return -1; - } - - return 0; - } - - /// - /// Compares two values and returns an integer that indicates whether the first value is less than, equal to, or greater than the second value. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// A signed integer that indicates the relative values of left and right, as shown in the following table. - /// - /// - /// Value - /// Condition - /// - /// - /// Less than zero - /// is less than . - /// - /// - /// Zero - /// equals . - /// - /// - /// Greater than zero - /// is greater than . - /// - /// - /// - public static int Compare(BigInteger left, BigInteger right) - { - int ls = left._sign; - int rs = right._sign; - - if (ls != rs) - { - return ls > rs ? 1 : -1; - } - - var r = CoreCompare(left._data, right._data); - if (ls < 0) - { - r = -r; - } - - return r; - } - - private static int TopByte(uint x) - { - if ((x & 0xFFFF0000u) != 0) - { - if ((x & 0xFF000000u) != 0) - { - return 4; - } - - return 3; - } - - if ((x & 0xFF00u) != 0) - { - return 2; - } - - return 1; - } - - private static int FirstNonFfByte(uint word) - { - if ((word & 0xFF000000u) != 0xFF000000u) - { - return 4; - } - - if ((word & 0xFF0000u) != 0xFF0000u) - { - return 3; - } - - if ((word & 0xFF00u) != 0xFF00u) - { - return 2; - } - - return 1; - } - - /// - /// Converts a value to a byte array. - /// - /// - /// The value of the current object converted to an array of bytes. - /// - public readonly byte[] ToByteArray() - { - if (_sign == 0) - { - return new byte[1]; - } - - // number of bytes not counting upper word - var bytes = (_data.Length - 1) * 4; - var needExtraZero = false; - - var topWord = _data[_data.Length - 1]; - int extra; - - // if the topmost bit is set we need an extra - if (_sign == 1) - { - extra = TopByte(topWord); - var mask = 0x80u << ((extra - 1) * 8); - if ((topWord & mask) != 0) - { - needExtraZero = true; - } - } - else - { - extra = TopByte(topWord); - } - - var res = new byte[bytes + extra + (needExtraZero ? 1 : 0)]; - if (_sign == 1) - { - var j = 0; - var end = _data.Length - 1; - for (var i = 0; i < end; ++i) - { - var word = _data[i]; - - res[j++] = (byte)word; - res[j++] = (byte)(word >> 8); - res[j++] = (byte)(word >> 16); - res[j++] = (byte)(word >> 24); - } - - while (extra-- > 0) - { - res[j++] = (byte)topWord; - topWord >>= 8; - } - } - else - { - var j = 0; - var end = _data.Length - 1; - - uint carry = 1, word; - ulong add; - for (var i = 0; i < end; ++i) - { - word = _data[i]; - add = (ulong)~word + carry; - word = (uint)add; - carry = (uint)(add >> 32); - - res[j++] = (byte)word; - res[j++] = (byte)(word >> 8); - res[j++] = (byte)(word >> 16); - res[j++] = (byte)(word >> 24); - } - - add = (ulong)~topWord + carry; - word = (uint)add; - carry = (uint)(add >> 32); - if (carry == 0) - { - var ex = FirstNonFfByte(word); - var needExtra = (word & (1 << ((ex * 8) - 1))) == 0; - var to = ex + (needExtra ? 1 : 0); - - if (to != extra) - { - Array.Resize(ref res, bytes + to); - } - - while (ex-- > 0) - { - res[j++] = (byte)word; - word >>= 8; - } - - if (needExtra) - { - res[j++] = 0xFF; - } - } - else - { - Array.Resize(ref res, bytes + 5); - res[j++] = (byte)word; - res[j++] = (byte)(word >> 8); - res[j++] = (byte)(word >> 16); - res[j++] = (byte)(word >> 24); - res[j++] = 0xFF; - } - } - - return res; - } - - private static uint[] CoreAdd(uint[] a, uint[] b) - { - if (a.Length < b.Length) - { - var tmp = a; - a = b; - b = tmp; - } - - var bl = a.Length; - var sl = b.Length; - - var res = new uint[bl]; - - ulong sum = 0; - - var i = 0; - for (; i < sl; i++) - { - sum = sum + a[i] + b[i]; - res[i] = (uint)sum; - sum >>= 32; - } - - for (; i < bl; i++) - { - sum += a[i]; - res[i] = (uint)sum; - sum >>= 32; - } - - if (sum != 0) - { - Array.Resize(ref res, bl + 1); - res[i] = (uint)sum; - } - - return res; - } - - private static uint[] CoreAdd(uint[] a, uint b) - { - var len = a.Length; - var res = new uint[len]; - - ulong sum = b; - int i; - for (i = 0; i < len; i++) - { - sum += a[i]; - res[i] = (uint)sum; - sum >>= 32; - } - - if (sum != 0) - { - Array.Resize(ref res, len + 1); - res[i] = (uint)sum; - } - - return res; - } - - /*invariant a > b*/ - private static uint[] CoreSub(uint[] a, uint[] b) - { - var bl = a.Length; - var sl = b.Length; - - var res = new uint[bl]; - - ulong borrow = 0; - int i; - for (i = 0; i < sl; ++i) - { - borrow = (ulong)a[i] - b[i] - borrow; - - res[i] = (uint)borrow; - borrow = (borrow >> 32) & 0x1; - } - - for (; i < bl; i++) - { - borrow = (ulong)a[i] - borrow; - res[i] = (uint)borrow; - borrow = (borrow >> 32) & 0x1; - } - - // remove extra zeroes - for (i = bl - 1; i >= 0 && res[i] == 0; --i) - { - // Intentionally empty block - } - - if (i < bl - 1) - { - Array.Resize(ref res, i + 1); - } - - return res; - } - - private static uint[] CoreSub(uint[] a, uint b) - { - var len = a.Length; - var res = new uint[len]; - - ulong borrow = b; - int i; - for (i = 0; i < len; i++) - { - borrow = (ulong)a[i] - borrow; - res[i] = (uint)borrow; - borrow = (borrow >> 32) & 0x1; - } - - // Remove extra zeroes - for (i = len - 1; i >= 0 && res[i] == 0; --i) - { - // Intentionally empty block - } - - if (i < len - 1) - { - Array.Resize(ref res, i + 1); - } - - return res; - } - - private static int CoreCompare(uint[] a, uint[] b) - { - var al = a != null ? a.Length : 0; - var bl = b != null ? b.Length : 0; - - if (al > bl) - { - return 1; - } - - if (bl > al) - { - return -1; - } - - for (var i = al - 1; i >= 0; --i) - { - var ai = a[i]; - var bi = b[i]; - if (ai > bi) - { - return 1; - } - - if (ai < bi) - { - return -1; - } - } - - return 0; - } - - private static int GetNormalizeShift(uint value) - { - var shift = 0; - - if ((value & 0xFFFF0000) == 0) - { - value <<= 16; - shift += 16; - } - - if ((value & 0xFF000000) == 0) - { - value <<= 8; - shift += 8; - } - - if ((value & 0xF0000000) == 0) - { - value <<= 4; - shift += 4; - } - - if ((value & 0xC0000000) == 0) - { - value <<= 2; - shift += 2; - } - - if ((value & 0x80000000) == 0) - { -#pragma warning disable IDE0059 // Unnecessary assignment of a value - value <<= 1; -#pragma warning restore IDE0059 // Unnecessary assignment of a value - shift += 1; - } - - return shift; - } - - private static void Normalize(uint[] u, int l, uint[] un, int shift) - { - uint carry = 0; - int i; - if (shift > 0) - { - var rshift = 32 - shift; - for (i = 0; i < l; i++) - { - var ui = u[i]; - un[i] = (ui << shift) | carry; - carry = ui >> rshift; - } - } - else - { - for (i = 0; i < l; i++) - { - un[i] = u[i]; - } - } - - while (i < un.Length) - { - un[i++] = 0; - } - - if (carry != 0) - { - un[l] = carry; - } - } - - private static void Unnormalize(uint[] un, out uint[] r, int shift) - { - var length = un.Length; - r = new uint[length]; - - if (shift > 0) - { - var lshift = 32 - shift; - uint carry = 0; - for (var i = length - 1; i >= 0; i--) - { - var uni = un[i]; - r[i] = (uni >> shift) | carry; - carry = uni << lshift; - } - } - else - { - for (var i = 0; i < length; i++) - { - r[i] = un[i]; - } - } - } - - private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] r) - { - var m = u.Length; - var n = v.Length; - - if (n <= 1) - { - // Divide by single digit - ulong rem = 0; - var v0 = v[0]; - q = new uint[m]; - r = new uint[1]; - - for (var j = m - 1; j >= 0; j--) - { - rem *= Base; - rem += u[j]; - - var div = rem / v0; - rem -= div * v0; - q[j] = (uint)div; - } - - r[0] = (uint)rem; - } - else if (m >= n) - { - var shift = GetNormalizeShift(v[n - 1]); - - var un = new uint[m + 1]; - var vn = new uint[n]; - - Normalize(u, m, un, shift); - Normalize(v, n, vn, shift); - - q = new uint[m - n + 1]; - - // Main division loop - for (var j = m - n; j >= 0; j--) - { - int i; - - var rr = (Base * un[j + n]) + un[j + n - 1]; - var qq = rr / vn[n - 1]; - rr -= qq * vn[n - 1]; - - for (; ; ) - { - // Estimate too big ? - if ((qq >= Base) || (qq * vn[n - 2] > ((rr * Base) + un[j + n - 2]))) - { - qq--; - rr += (ulong)vn[n - 1]; - if (rr < Base) - { - continue; - } - } - - break; - } - - // Multiply and subtract - long b = 0; - long t; - for (i = 0; i < n; i++) - { - var p = vn[i] * qq; - t = (long)un[i + j] - (long)(uint)p - b; - un[i + j] = (uint)t; - p >>= 32; - t >>= 32; - b = (long)p - t; - } - - t = (long)un[j + n] - b; - un[j + n] = (uint)t; - - // Store the calculated value - q[j] = (uint)qq; - - // Add back vn[0..n] to un[j..j+n] - if (t < 0) - { - q[j]--; - ulong c = 0; - for (i = 0; i < n; i++) - { - c = (ulong)vn[i] + un[j + i] + c; - un[j + i] = (uint)c; - c >>= 32; - } - - c += (ulong)un[j + n]; - un[j + n] = (uint)c; - } - } - - Unnormalize(un, out r, shift); - } - else - { - q = new uint[] { 0 }; - r = u; - } - } - } -} diff --git a/src/Renci.SshNet/Common/DerData.cs b/src/Renci.SshNet/Common/DerData.cs index 6e917745e..cd77c0e08 100644 --- a/src/Renci.SshNet/Common/DerData.cs +++ b/src/Renci.SshNet/Common/DerData.cs @@ -1,6 +1,7 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; +using System.Numerics; namespace Renci.SshNet.Common { @@ -96,7 +97,11 @@ public BigInteger ReadBigInteger() var data = ReadBytes(length); +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + return new BigInteger(data, isBigEndian: true); +#else return new BigInteger(data.Reverse()); +#endif } /// @@ -213,7 +218,7 @@ public void Write(uint data) /// BigInteger data to write. public void Write(BigInteger data) { - var bytes = data.ToByteArray().Reverse(); + var bytes = data.ToByteArray(isBigEndian: true); _data.Add(Integer); var length = GetLength(bytes.Length); WriteBytes(length); diff --git a/src/Renci.SshNet/Common/Extensions.cs b/src/Renci.SshNet/Common/Extensions.cs index 7e6e8cb90..2ead4d7bf 100644 --- a/src/Renci.SshNet/Common/Extensions.cs +++ b/src/Renci.SshNet/Common/Extensions.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.Net; using System.Net.Sockets; +using System.Numerics; using System.Text; using Renci.SshNet.Abstractions; @@ -14,7 +15,7 @@ namespace Renci.SshNet.Common /// /// Collection of different extension methods. /// - internal static partial class Extensions + internal static class Extensions { internal static byte[] ToArray(this ServiceName serviceName) { @@ -45,9 +46,13 @@ internal static ServiceName ToServiceName(this byte[] data) internal static BigInteger ToBigInteger(this byte[] data) { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + return new BigInteger(data, isBigEndian: true); +#else var reversed = new byte[data.Length]; Buffer.BlockCopy(data, 0, reversed, 0, data.Length); return new BigInteger(reversed.Reverse()); +#endif } /// @@ -55,16 +60,21 @@ internal static BigInteger ToBigInteger(this byte[] data) /// public static BigInteger ToBigInteger2(this byte[] data) { +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + return new BigInteger(data, isBigEndian: true, isUnsigned: true); +#else if ((data[0] & (1 << 7)) != 0) { var buf = new byte[data.Length + 1]; Buffer.BlockCopy(data, 0, buf, 1, data.Length); - data = buf; + return new BigInteger(buf.Reverse()); } return data.ToBigInteger(); +#endif } +#if NETFRAMEWORK || NETSTANDARD2_0 public static byte[] ToByteArray(this BigInteger bigInt, bool isUnsigned = false, bool isBigEndian = false) { var data = bigInt.ToByteArray(); @@ -81,6 +91,15 @@ public static byte[] ToByteArray(this BigInteger bigInt, bool isUnsigned = false return data; } +#endif + +#if !NET6_0_OR_GREATER + public static long GetBitLength(this BigInteger bigint) + { + // Taken from https://github.com/dotnet/runtime/issues/31308 + return (long)Math.Ceiling(BigInteger.Log(bigint.Sign < 0 ? -bigint : bigint + 1, 2)); + } +#endif // See https://github.com/dotnet/runtime/blob/9b57a265c7efd3732b035bade005561a04767128/src/libraries/Common/src/System/Security/Cryptography/KeyBlobHelpers.cs#L51 public static byte[] ExportKeyParameter(this BigInteger value, int length) diff --git a/src/Renci.SshNet/Common/SshData.cs b/src/Renci.SshNet/Common/SshData.cs index 6f1e3d6d8..fc1417602 100644 --- a/src/Renci.SshNet/Common/SshData.cs +++ b/src/Renci.SshNet/Common/SshData.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Numerics; using System.Text; namespace Renci.SshNet.Common diff --git a/src/Renci.SshNet/Common/SshDataStream.cs b/src/Renci.SshNet/Common/SshDataStream.cs index a99e4010e..bb75a8715 100644 --- a/src/Renci.SshNet/Common/SshDataStream.cs +++ b/src/Renci.SshNet/Common/SshDataStream.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.IO; +using System.Numerics; using System.Text; namespace Renci.SshNet.Common @@ -110,7 +111,8 @@ public void Write(ulong value) /// The to write. public void Write(BigInteger data) { - var bytes = data.ToByteArray().Reverse(); + var bytes = data.ToByteArray(isBigEndian: true); + WriteBinary(bytes, 0, bytes.Length); } @@ -211,9 +213,13 @@ public void WriteBinary(byte[] buffer, int offset, int count) /// public BigInteger ReadBigInt() { - var length = ReadUInt32(); - var data = ReadBytes((int)length); + var data = ReadBinary(); + +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + return new BigInteger(data, isBigEndian: true); +#else return new BigInteger(data.Reverse()); +#endif } /// diff --git a/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeGroup.cs b/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeGroup.cs index a17c23e33..f2cb1eb4c 100644 --- a/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeGroup.cs +++ b/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeGroup.cs @@ -1,4 +1,6 @@ -using Renci.SshNet.Common; +using System.Numerics; + +using Renci.SshNet.Common; namespace Renci.SshNet.Messages.Transport { diff --git a/src/Renci.SshNet/Messages/Transport/KeyExchangeEcdhInitMessage.cs b/src/Renci.SshNet/Messages/Transport/KeyExchangeEcdhInitMessage.cs index 8f3ecee56..c4d3a6168 100644 --- a/src/Renci.SshNet/Messages/Transport/KeyExchangeEcdhInitMessage.cs +++ b/src/Renci.SshNet/Messages/Transport/KeyExchangeEcdhInitMessage.cs @@ -1,7 +1,5 @@ using System; -using Renci.SshNet.Common; - namespace Renci.SshNet.Messages.Transport { /// @@ -57,21 +55,6 @@ public KeyExchangeEcdhInitMessage(byte[] q) QC = q; } - /// - /// Initializes a new instance of the class. - /// - public KeyExchangeEcdhInitMessage(BigInteger d, BigInteger q) - { - var dBytes = d.ToByteArray().Reverse(); - var qBytes = q.ToByteArray().Reverse(); - - var data = new byte[dBytes.Length + qBytes.Length + 1]; - data[0] = 0x04; - Buffer.BlockCopy(dBytes, 0, data, 1, dBytes.Length); - Buffer.BlockCopy(qBytes, 0, data, dBytes.Length + 1, qBytes.Length); - QC = data; - } - /// /// Called when type specific data need to be loaded. /// diff --git a/src/Renci.SshNet/PrivateKeyFile.cs b/src/Renci.SshNet/PrivateKeyFile.cs index b0ed8668f..93848c095 100644 --- a/src/Renci.SshNet/PrivateKeyFile.cs +++ b/src/Renci.SshNet/PrivateKeyFile.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Globalization; using System.IO; +using System.Numerics; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; @@ -713,22 +714,17 @@ public BigInteger ReadBigIntWithBits() length = (length + 7) / 8; - var data = base.ReadBytes(length); - var bytesArray = new byte[data.Length + 1]; - Buffer.BlockCopy(data, 0, bytesArray, 1, data.Length); - - return new BigInteger(bytesArray.Reverse()); + return base.ReadBytes(length).ToBigInteger2(); } public BigInteger ReadBignum() { - return new BigInteger(ReadBignum2().Reverse()); + return DataStream.ReadBigInt(); } public byte[] ReadBignum2() { - var length = (int)base.ReadUInt32(); - return base.ReadBytes(length); + return ReadBinary(); } protected override void LoadData() diff --git a/src/Renci.SshNet/Security/Cryptography/DsaKey.cs b/src/Renci.SshNet/Security/Cryptography/DsaKey.cs index 252dfeee2..2d7c35011 100644 --- a/src/Renci.SshNet/Security/Cryptography/DsaKey.cs +++ b/src/Renci.SshNet/Security/Cryptography/DsaKey.cs @@ -1,5 +1,6 @@ #nullable enable using System; +using System.Numerics; using System.Security.Cryptography; using Renci.SshNet.Common; @@ -46,7 +47,7 @@ public override int KeyLength { get { - return P.BitLength; + return (int)P.GetBitLength(); } } diff --git a/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs b/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs index b1cfd99cb..7f31ac887 100644 --- a/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs +++ b/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs @@ -1,4 +1,5 @@ using System; +using System.Numerics; using Org.BouncyCastle.Math.EC.Rfc8032; @@ -87,7 +88,8 @@ public ED25519Key(SshKeyData publicKeyData) throw new ArgumentException($"Invalid Ed25519 public key data ({publicKeyData.Name}, {publicKeyData.Keys.Length}).", nameof(publicKeyData)); } - PublicKey = publicKeyData.Keys[0].ToByteArray().Reverse().TrimLeadingZeros().Pad(Ed25519.PublicKeySize); + PublicKey = publicKeyData.Keys[0].ToByteArray(isBigEndian: true).TrimLeadingZeros().Pad(Ed25519.PublicKeySize); + PrivateKey = new byte[Ed25519.SecretKeySize]; } /// diff --git a/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs b/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs index f5e577c06..daaf29cd5 100644 --- a/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs +++ b/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs @@ -95,11 +95,11 @@ public byte[] Signature { var signed_r = new byte[_signature_size / 2]; Buffer.BlockCopy(value, 0, signed_r, 0, signed_r.Length); - _signature_r = signed_r.ToBigInteger2().ToByteArray().Reverse(); + _signature_r = signed_r.ToBigInteger2().ToByteArray(isBigEndian: true); var signed_s = new byte[_signature_size / 2]; Buffer.BlockCopy(value, signed_r.Length, signed_s, 0, signed_s.Length); - _signature_s = signed_s.ToBigInteger2().ToByteArray().Reverse(); + _signature_s = signed_s.ToBigInteger2().ToByteArray(isBigEndian: true); } } @@ -122,8 +122,8 @@ protected override void LoadData() protected override void SaveData() { - WriteBinaryString(_signature_r.ToBigInteger2().ToByteArray().Reverse()); - WriteBinaryString(_signature_s.ToBigInteger2().ToByteArray().Reverse()); + WriteBinaryString(_signature_r.ToBigInteger2().ToByteArray(isBigEndian: true)); + WriteBinaryString(_signature_s.ToBigInteger2().ToByteArray(isBigEndian: true)); } protected override int BufferCapacity diff --git a/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs b/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs index 3307eba8b..718d5170a 100644 --- a/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs +++ b/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs @@ -1,6 +1,7 @@ -#nullable enable +#nullable enable using System; using System.Diagnostics; +using System.Numerics; using System.Security.Cryptography; using System.Text; @@ -145,7 +146,11 @@ public override BigInteger[] Public Buffer.BlockCopy(qy, 0, q, qx.Length + 1, qy.Length); // returns Curve-Name and x/y as ECPoint +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER + return new[] { curve, new BigInteger(q, isBigEndian: true) }; +#else return new[] { curve, new BigInteger(q.Reverse()) }; +#endif } } @@ -191,10 +196,10 @@ public EcdsaKey(SshKeyData publicKeyData) throw new ArgumentException($"Invalid ECDSA public key data. ({publicKeyData.Name}, {publicKeyData.Keys.Length}).", nameof(publicKeyData)); } - var curve_s = Encoding.ASCII.GetString(publicKeyData.Keys[0].ToByteArray().Reverse()); + var curve_s = Encoding.ASCII.GetString(publicKeyData.Keys[0].ToByteArray(isBigEndian: true)); var curve_oid = GetCurveOid(curve_s); - var publickey = publicKeyData.Keys[1].ToByteArray().Reverse(); + var publickey = publicKeyData.Keys[1].ToByteArray(isBigEndian: true); _impl = Import(curve_oid, publickey, privatekey: null); } diff --git a/src/Renci.SshNet/Security/Cryptography/Key.cs b/src/Renci.SshNet/Security/Cryptography/Key.cs index 83f6c16c0..45a58df48 100644 --- a/src/Renci.SshNet/Security/Cryptography/Key.cs +++ b/src/Renci.SshNet/Security/Cryptography/Key.cs @@ -1,4 +1,5 @@ -using Renci.SshNet.Common; +using System.Numerics; + using Renci.SshNet.Security.Cryptography; namespace Renci.SshNet.Security diff --git a/src/Renci.SshNet/Security/Cryptography/RsaKey.cs b/src/Renci.SshNet/Security/Cryptography/RsaKey.cs index 229d448b3..84fd14c91 100644 --- a/src/Renci.SshNet/Security/Cryptography/RsaKey.cs +++ b/src/Renci.SshNet/Security/Cryptography/RsaKey.cs @@ -1,5 +1,6 @@ #nullable enable using System; +using System.Numerics; using System.Security.Cryptography; using Renci.SshNet.Common; @@ -96,7 +97,7 @@ public override int KeyLength { get { - return Modulus.BitLength; + return (int)Modulus.GetBitLength(); } } diff --git a/src/Renci.SshNet/Security/GroupExchangeHashData.cs b/src/Renci.SshNet/Security/GroupExchangeHashData.cs index 57fe2e83c..9f9bee54c 100644 --- a/src/Renci.SshNet/Security/GroupExchangeHashData.cs +++ b/src/Renci.SshNet/Security/GroupExchangeHashData.cs @@ -1,4 +1,5 @@ using System; +using System.Numerics; using Renci.SshNet.Common; @@ -38,13 +39,13 @@ public string ClientVersion public BigInteger Prime { private get { return _prime.ToBigInteger(); } - set { _prime = value.ToByteArray().Reverse(); } + set { _prime = value.ToByteArray(isBigEndian: true); } } public BigInteger SubGroup { private get { return _subGroup.ToBigInteger(); } - set { _subGroup = value.ToByteArray().Reverse(); } + set { _subGroup = value.ToByteArray(isBigEndian: true); } } public byte[] ClientExchangeValue { get; set; } diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs index 7dfc51e34..35ffb971a 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs @@ -1,5 +1,7 @@ using System; +using System.Numerics; +using Renci.SshNet.Abstractions; using Renci.SshNet.Common; using Renci.SshNet.Messages.Transport; @@ -109,14 +111,26 @@ protected void PopulateClientExchangeValue() do { // Create private component - _privateExponent = BigInteger.Random(privateExponentSize); + _privateExponent = RandomBigInt(privateExponentSize); // Generate public component clientExchangeValue = BigInteger.ModPow(_group, _privateExponent, _prime); } while (clientExchangeValue < 1 || clientExchangeValue > (_prime - 1)); - _clientExchangeValue = clientExchangeValue.ToByteArray().Reverse(); + _clientExchangeValue = clientExchangeValue.ToByteArray(isBigEndian: true); + } + + /// + /// Generates a new, random of the specified length. + /// + /// The number of bits for the new number. + /// A random number of the specified length. + private static BigInteger RandomBigInt(int bitLength) + { + var bytesArray = CryptoAbstraction.GenerateRandom((bitLength / 8) + (((bitLength % 8) > 0) ? 1 : 0)); + bytesArray[bytesArray.Length - 1] = (byte)(bytesArray[bytesArray.Length - 1] & 0x7F); // Ensure not a negative value + return new BigInteger(bytesArray); } /// @@ -129,7 +143,7 @@ protected virtual void HandleServerDhReply(byte[] hostKey, byte[] serverExchange { _serverExchangeValue = serverExchangeValue; _hostKey = hostKey; - SharedKey = BigInteger.ModPow(serverExchangeValue.ToBigInteger(), _privateExponent, _prime).ToByteArray().Reverse(); + SharedKey = BigInteger.ModPow(serverExchangeValue.ToBigInteger(), _privateExponent, _prime).ToByteArray(isBigEndian: true); _signature = signature; } } diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha1.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha1.cs index be0bfe745..d328cd5ae 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha1.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha1.cs @@ -1,4 +1,4 @@ -using Renci.SshNet.Common; +using System.Numerics; namespace Renci.SshNet.Security { @@ -10,32 +10,32 @@ internal sealed class KeyExchangeDiffieHellmanGroup14Sha1 : KeyExchangeDiffieHel /// /// Defined in https://tools.ietf.org/html/rfc2409#section-6.2. /// - private static readonly byte[] SecondOkleyGroupReversed = - { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x68, 0xaa, 0xac, 0x8a, - 0x5a, 0x8e, 0x72, 0x15, 0x10, 0x05, 0xfa, 0x98, 0x18, 0x26, 0xd2, 0x15, - 0xe5, 0x6a, 0x95, 0xea, 0x7c, 0x49, 0x95, 0x39, 0x18, 0x17, 0x58, 0x95, - 0xf6, 0xcb, 0x2b, 0xde, 0xc9, 0x52, 0x4c, 0x6f, 0xf0, 0x5d, 0xc5, 0xb5, - 0x8f, 0xa2, 0x07, 0xec, 0xa2, 0x83, 0x27, 0x9b, 0x03, 0x86, 0x0e, 0x18, - 0x2c, 0x77, 0x9e, 0xe3, 0x3b, 0xce, 0x36, 0x2e, 0x46, 0x5e, 0x90, 0x32, - 0x7c, 0x21, 0x18, 0xca, 0x08, 0x6c, 0x74, 0xf1, 0x04, 0x98, 0xbc, 0x4a, - 0x4e, 0x35, 0x0c, 0x67, 0x6d, 0x96, 0x96, 0x70, 0x07, 0x29, 0xd5, 0x9e, - 0xbb, 0x52, 0x85, 0x20, 0x56, 0xf3, 0x62, 0x1c, 0x96, 0xad, 0xa3, 0xdc, - 0x23, 0x5d, 0x65, 0x83, 0x5f, 0xcf, 0x24, 0xfd, 0xa8, 0x3f, 0x16, 0x69, - 0x9a, 0xd3, 0x55, 0x1c, 0x36, 0x48, 0xda, 0x98, 0x05, 0xbf, 0x63, 0xa1, - 0xb8, 0x7c, 0x00, 0xc2, 0x3d, 0x5b, 0xe4, 0xec, 0x51, 0x66, 0x28, 0x49, - 0xe6, 0x1f, 0x4b, 0x7c, 0x11, 0x24, 0x9f, 0xae, 0xa5, 0x9f, 0x89, 0x5a, - 0xfb, 0x6b, 0x38, 0xee, 0xed, 0xb7, 0x06, 0xf4, 0xb6, 0x5c, 0xff, 0x0b, - 0x6b, 0xed, 0x37, 0xa6, 0xe9, 0x42, 0x4c, 0xf4, 0xc6, 0x7e, 0x5e, 0x62, - 0x76, 0xb5, 0x85, 0xe4, 0x45, 0xc2, 0x51, 0x6d, 0x6d, 0x35, 0xe1, 0x4f, - 0x37, 0x14, 0x5f, 0xf2, 0x6d, 0x0a, 0x2b, 0x30, 0x1b, 0x43, 0x3a, 0xcd, - 0xb3, 0x19, 0x95, 0xef, 0xdd, 0x04, 0x34, 0x8e, 0x79, 0x08, 0x4a, 0x51, - 0x22, 0x9b, 0x13, 0x3b, 0xa6, 0xbe, 0x0b, 0x02, 0x74, 0xcc, 0x67, 0x8a, - 0x08, 0x4e, 0x02, 0x29, 0xd1, 0x1c, 0xdc, 0x80, 0x8b, 0x62, 0xc6, 0xc4, - 0x34, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0x0f, 0xc9, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x00 - }; + private static readonly BigInteger SecondOkleyGroupReversed = new BigInteger( + [ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x68, 0xaa, 0xac, 0x8a, + 0x5a, 0x8e, 0x72, 0x15, 0x10, 0x05, 0xfa, 0x98, 0x18, 0x26, 0xd2, 0x15, + 0xe5, 0x6a, 0x95, 0xea, 0x7c, 0x49, 0x95, 0x39, 0x18, 0x17, 0x58, 0x95, + 0xf6, 0xcb, 0x2b, 0xde, 0xc9, 0x52, 0x4c, 0x6f, 0xf0, 0x5d, 0xc5, 0xb5, + 0x8f, 0xa2, 0x07, 0xec, 0xa2, 0x83, 0x27, 0x9b, 0x03, 0x86, 0x0e, 0x18, + 0x2c, 0x77, 0x9e, 0xe3, 0x3b, 0xce, 0x36, 0x2e, 0x46, 0x5e, 0x90, 0x32, + 0x7c, 0x21, 0x18, 0xca, 0x08, 0x6c, 0x74, 0xf1, 0x04, 0x98, 0xbc, 0x4a, + 0x4e, 0x35, 0x0c, 0x67, 0x6d, 0x96, 0x96, 0x70, 0x07, 0x29, 0xd5, 0x9e, + 0xbb, 0x52, 0x85, 0x20, 0x56, 0xf3, 0x62, 0x1c, 0x96, 0xad, 0xa3, 0xdc, + 0x23, 0x5d, 0x65, 0x83, 0x5f, 0xcf, 0x24, 0xfd, 0xa8, 0x3f, 0x16, 0x69, + 0x9a, 0xd3, 0x55, 0x1c, 0x36, 0x48, 0xda, 0x98, 0x05, 0xbf, 0x63, 0xa1, + 0xb8, 0x7c, 0x00, 0xc2, 0x3d, 0x5b, 0xe4, 0xec, 0x51, 0x66, 0x28, 0x49, + 0xe6, 0x1f, 0x4b, 0x7c, 0x11, 0x24, 0x9f, 0xae, 0xa5, 0x9f, 0x89, 0x5a, + 0xfb, 0x6b, 0x38, 0xee, 0xed, 0xb7, 0x06, 0xf4, 0xb6, 0x5c, 0xff, 0x0b, + 0x6b, 0xed, 0x37, 0xa6, 0xe9, 0x42, 0x4c, 0xf4, 0xc6, 0x7e, 0x5e, 0x62, + 0x76, 0xb5, 0x85, 0xe4, 0x45, 0xc2, 0x51, 0x6d, 0x6d, 0x35, 0xe1, 0x4f, + 0x37, 0x14, 0x5f, 0xf2, 0x6d, 0x0a, 0x2b, 0x30, 0x1b, 0x43, 0x3a, 0xcd, + 0xb3, 0x19, 0x95, 0xef, 0xdd, 0x04, 0x34, 0x8e, 0x79, 0x08, 0x4a, 0x51, + 0x22, 0x9b, 0x13, 0x3b, 0xa6, 0xbe, 0x0b, 0x02, 0x74, 0xcc, 0x67, 0x8a, + 0x08, 0x4e, 0x02, 0x29, 0xd1, 0x1c, 0xdc, 0x80, 0x8b, 0x62, 0xc6, 0xc4, + 0x34, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0x0f, 0xc9, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00 + ]); /// /// Gets algorithm name. @@ -55,7 +55,7 @@ public override BigInteger GroupPrime { get { - return new BigInteger(SecondOkleyGroupReversed); + return SecondOkleyGroupReversed; } } } diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha256.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha256.cs index 9687875e7..ab8a9cef6 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha256.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha256.cs @@ -1,4 +1,4 @@ -using Renci.SshNet.Common; +using System.Numerics; namespace Renci.SshNet.Security { @@ -10,32 +10,32 @@ internal sealed class KeyExchangeDiffieHellmanGroup14Sha256 : KeyExchangeDiffieH /// /// Defined in https://tools.ietf.org/html/rfc2409#section-6.2. /// - private static readonly byte[] SecondOkleyGroupReversed = - { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x68, 0xaa, 0xac, 0x8a, - 0x5a, 0x8e, 0x72, 0x15, 0x10, 0x05, 0xfa, 0x98, 0x18, 0x26, 0xd2, 0x15, - 0xe5, 0x6a, 0x95, 0xea, 0x7c, 0x49, 0x95, 0x39, 0x18, 0x17, 0x58, 0x95, - 0xf6, 0xcb, 0x2b, 0xde, 0xc9, 0x52, 0x4c, 0x6f, 0xf0, 0x5d, 0xc5, 0xb5, - 0x8f, 0xa2, 0x07, 0xec, 0xa2, 0x83, 0x27, 0x9b, 0x03, 0x86, 0x0e, 0x18, - 0x2c, 0x77, 0x9e, 0xe3, 0x3b, 0xce, 0x36, 0x2e, 0x46, 0x5e, 0x90, 0x32, - 0x7c, 0x21, 0x18, 0xca, 0x08, 0x6c, 0x74, 0xf1, 0x04, 0x98, 0xbc, 0x4a, - 0x4e, 0x35, 0x0c, 0x67, 0x6d, 0x96, 0x96, 0x70, 0x07, 0x29, 0xd5, 0x9e, - 0xbb, 0x52, 0x85, 0x20, 0x56, 0xf3, 0x62, 0x1c, 0x96, 0xad, 0xa3, 0xdc, - 0x23, 0x5d, 0x65, 0x83, 0x5f, 0xcf, 0x24, 0xfd, 0xa8, 0x3f, 0x16, 0x69, - 0x9a, 0xd3, 0x55, 0x1c, 0x36, 0x48, 0xda, 0x98, 0x05, 0xbf, 0x63, 0xa1, - 0xb8, 0x7c, 0x00, 0xc2, 0x3d, 0x5b, 0xe4, 0xec, 0x51, 0x66, 0x28, 0x49, - 0xe6, 0x1f, 0x4b, 0x7c, 0x11, 0x24, 0x9f, 0xae, 0xa5, 0x9f, 0x89, 0x5a, - 0xfb, 0x6b, 0x38, 0xee, 0xed, 0xb7, 0x06, 0xf4, 0xb6, 0x5c, 0xff, 0x0b, - 0x6b, 0xed, 0x37, 0xa6, 0xe9, 0x42, 0x4c, 0xf4, 0xc6, 0x7e, 0x5e, 0x62, - 0x76, 0xb5, 0x85, 0xe4, 0x45, 0xc2, 0x51, 0x6d, 0x6d, 0x35, 0xe1, 0x4f, - 0x37, 0x14, 0x5f, 0xf2, 0x6d, 0x0a, 0x2b, 0x30, 0x1b, 0x43, 0x3a, 0xcd, - 0xb3, 0x19, 0x95, 0xef, 0xdd, 0x04, 0x34, 0x8e, 0x79, 0x08, 0x4a, 0x51, - 0x22, 0x9b, 0x13, 0x3b, 0xa6, 0xbe, 0x0b, 0x02, 0x74, 0xcc, 0x67, 0x8a, - 0x08, 0x4e, 0x02, 0x29, 0xd1, 0x1c, 0xdc, 0x80, 0x8b, 0x62, 0xc6, 0xc4, - 0x34, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0x0f, 0xc9, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x00 - }; + private static readonly BigInteger SecondOkleyGroupReversed = new BigInteger( + [ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x68, 0xaa, 0xac, 0x8a, + 0x5a, 0x8e, 0x72, 0x15, 0x10, 0x05, 0xfa, 0x98, 0x18, 0x26, 0xd2, 0x15, + 0xe5, 0x6a, 0x95, 0xea, 0x7c, 0x49, 0x95, 0x39, 0x18, 0x17, 0x58, 0x95, + 0xf6, 0xcb, 0x2b, 0xde, 0xc9, 0x52, 0x4c, 0x6f, 0xf0, 0x5d, 0xc5, 0xb5, + 0x8f, 0xa2, 0x07, 0xec, 0xa2, 0x83, 0x27, 0x9b, 0x03, 0x86, 0x0e, 0x18, + 0x2c, 0x77, 0x9e, 0xe3, 0x3b, 0xce, 0x36, 0x2e, 0x46, 0x5e, 0x90, 0x32, + 0x7c, 0x21, 0x18, 0xca, 0x08, 0x6c, 0x74, 0xf1, 0x04, 0x98, 0xbc, 0x4a, + 0x4e, 0x35, 0x0c, 0x67, 0x6d, 0x96, 0x96, 0x70, 0x07, 0x29, 0xd5, 0x9e, + 0xbb, 0x52, 0x85, 0x20, 0x56, 0xf3, 0x62, 0x1c, 0x96, 0xad, 0xa3, 0xdc, + 0x23, 0x5d, 0x65, 0x83, 0x5f, 0xcf, 0x24, 0xfd, 0xa8, 0x3f, 0x16, 0x69, + 0x9a, 0xd3, 0x55, 0x1c, 0x36, 0x48, 0xda, 0x98, 0x05, 0xbf, 0x63, 0xa1, + 0xb8, 0x7c, 0x00, 0xc2, 0x3d, 0x5b, 0xe4, 0xec, 0x51, 0x66, 0x28, 0x49, + 0xe6, 0x1f, 0x4b, 0x7c, 0x11, 0x24, 0x9f, 0xae, 0xa5, 0x9f, 0x89, 0x5a, + 0xfb, 0x6b, 0x38, 0xee, 0xed, 0xb7, 0x06, 0xf4, 0xb6, 0x5c, 0xff, 0x0b, + 0x6b, 0xed, 0x37, 0xa6, 0xe9, 0x42, 0x4c, 0xf4, 0xc6, 0x7e, 0x5e, 0x62, + 0x76, 0xb5, 0x85, 0xe4, 0x45, 0xc2, 0x51, 0x6d, 0x6d, 0x35, 0xe1, 0x4f, + 0x37, 0x14, 0x5f, 0xf2, 0x6d, 0x0a, 0x2b, 0x30, 0x1b, 0x43, 0x3a, 0xcd, + 0xb3, 0x19, 0x95, 0xef, 0xdd, 0x04, 0x34, 0x8e, 0x79, 0x08, 0x4a, 0x51, + 0x22, 0x9b, 0x13, 0x3b, 0xa6, 0xbe, 0x0b, 0x02, 0x74, 0xcc, 0x67, 0x8a, + 0x08, 0x4e, 0x02, 0x29, 0xd1, 0x1c, 0xdc, 0x80, 0x8b, 0x62, 0xc6, 0xc4, + 0x34, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0x0f, 0xc9, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00 + ]); /// /// Gets algorithm name. @@ -55,7 +55,7 @@ public override BigInteger GroupPrime { get { - return new BigInteger(SecondOkleyGroupReversed); + return SecondOkleyGroupReversed; } } } diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup16Sha512.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup16Sha512.cs index ba8403fec..e212821e5 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup16Sha512.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup16Sha512.cs @@ -1,4 +1,4 @@ -using Renci.SshNet.Common; +using System.Numerics; namespace Renci.SshNet.Security { @@ -10,48 +10,48 @@ internal sealed class KeyExchangeDiffieHellmanGroup16Sha512 : KeyExchangeDiffieH /// /// Defined in https://tools.ietf.org/html/rfc3526#section-5. /// - private static readonly byte[] MoreModularExponentialGroup16Reversed = - { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x99, 0x31, 0x06, 0x34, 0xc9, 0x35, 0xf4, 0x4d, - 0x8f, 0xc0, 0xa6, 0x90, 0xdc, 0xb7, 0xff, 0x86, 0xc1, 0xdd, 0x8f, 0x8d, 0x98, 0xea, 0xb4, 0x93, - 0xa9, 0x5a, 0xb0, 0xd5, 0x27, 0x91, 0x06, 0xd0, 0x1c, 0x48, 0x70, 0x21, 0x76, 0xdd, 0x1b, 0xb8, - 0xaf, 0xd7, 0xe2, 0xce, 0x70, 0x29, 0x61, 0x1f, 0xed, 0xe7, 0x5b, 0x51, 0x86, 0xa1, 0x3b, 0x23, - 0xa2, 0xc3, 0x90, 0xa0, 0x4f, 0x96, 0xb2, 0x99, 0x5d, 0xc0, 0x6b, 0x4e, 0x47, 0x59, 0x7c, 0x28, - 0xa6, 0xca, 0xbe, 0x1f, 0x14, 0xfc, 0x8e, 0x2e, 0xf9, 0x8e, 0xde, 0x04, 0xdb, 0xc2, 0xbb, 0xdb, - 0xe8, 0x4c, 0xd4, 0x2a, 0xca, 0xe9, 0x83, 0x25, 0xda, 0x0b, 0x15, 0xb6, 0x34, 0x68, 0x94, 0x1a, - 0x3c, 0xe2, 0xf4, 0x6a, 0x18, 0x27, 0xc3, 0x99, 0x26, 0x5b, 0xba, 0xbd, 0x10, 0x9a, 0x71, 0x88, - 0xd7, 0xe6, 0x87, 0xa7, 0x12, 0x3c, 0x72, 0x1a, 0x01, 0x08, 0x21, 0xa9, 0x20, 0xd1, 0x82, 0x4b, - 0x8e, 0x10, 0xfd, 0xe0, 0xfc, 0x5b, 0xdb, 0x43, 0x31, 0xab, 0xe5, 0x74, 0xa0, 0x4f, 0xe2, 0x08, - 0xe2, 0x46, 0xd9, 0xba, 0xc0, 0x88, 0x09, 0x77, 0x6c, 0x5d, 0x61, 0x7a, 0x57, 0x17, 0xe1, 0xbb, - 0x0c, 0x20, 0x7b, 0x17, 0x18, 0x2b, 0x1f, 0x52, 0x64, 0x6a, 0xc8, 0x3e, 0x73, 0x02, 0x76, 0xd8, - 0x64, 0x08, 0x8a, 0xd9, 0x06, 0xfa, 0x2f, 0xf1, 0x6b, 0xee, 0xd2, 0x1a, 0x26, 0xd2, 0xe3, 0xce, - 0x9d, 0x61, 0x25, 0x4a, 0xe0, 0x94, 0x8c, 0x1e, 0xd7, 0x33, 0x09, 0xdb, 0x8c, 0xae, 0xf5, 0xab, - 0xc7, 0xe4, 0xe1, 0xa6, 0x85, 0x0f, 0x97, 0xb3, 0x7d, 0x0c, 0x06, 0x5d, 0x57, 0x71, 0xea, 0x8a, - 0x0a, 0xef, 0xdb, 0x58, 0x04, 0x85, 0xfb, 0xec, 0x64, 0xba, 0x1c, 0xdf, 0xab, 0x21, 0x55, 0xa8, - 0x33, 0x7a, 0x50, 0x04, 0x0d, 0x17, 0x33, 0xad, 0x2d, 0xc4, 0xaa, 0x8a, 0x5a, 0x8e, 0x72, 0x15, - 0x10, 0x05, 0xfa, 0x98, 0x18, 0x26, 0xd2, 0x15, 0xe5, 0x6a, 0x95, 0xea, 0x7c, 0x49, 0x95, 0x39, - 0x18, 0x17, 0x58, 0x95, 0xf6, 0xcb, 0x2b, 0xde, 0xc9, 0x52, 0x4c, 0x6f, 0xf0, 0x5d, 0xc5, 0xb5, - 0x8f, 0xa2, 0x07, 0xec, 0xa2, 0x83, 0x27, 0x9b, 0x03, 0x86, 0x0e, 0x18, 0x2c, 0x77, 0x9e, 0xe3, - 0x3b, 0xce, 0x36, 0x2e, 0x46, 0x5e, 0x90, 0x32, 0x7c, 0x21, 0x18, 0xca, 0x08, 0x6c, 0x74, 0xf1, - 0x04, 0x98, 0xbc, 0x4a, 0x4e, 0x35, 0x0c, 0x67, 0x6d, 0x96, 0x96, 0x70, 0x07, 0x29, 0xd5, 0x9e, - 0xbb, 0x52, 0x85, 0x20, 0x56, 0xf3, 0x62, 0x1c, 0x96, 0xad, 0xa3, 0xdc, 0x23, 0x5d, 0x65, 0x83, - 0x5f, 0xcf, 0x24, 0xfd, 0xa8, 0x3f, 0x16, 0x69, 0x9a, 0xd3, 0x55, 0x1c, 0x36, 0x48, 0xda, 0x98, - 0x05, 0xbf, 0x63, 0xa1, 0xb8, 0x7c, 0x00, 0xc2, 0x3d, 0x5b, 0xe4, 0xec, 0x51, 0x66, 0x28, 0x49, - 0xe6, 0x1f, 0x4b, 0x7c, 0x11, 0x24, 0x9f, 0xae, 0xa5, 0x9f, 0x89, 0x5a, 0xfb, 0x6b, 0x38, 0xee, - 0xed, 0xb7, 0x06, 0xf4, 0xb6, 0x5c, 0xff, 0x0b, 0x6b, 0xed, 0x37, 0xa6, 0xe9, 0x42, 0x4c, 0xf4, - 0xc6, 0x7e, 0x5e, 0x62, 0x76, 0xb5, 0x85, 0xe4, 0x45, 0xc2, 0x51, 0x6d, 0x6d, 0x35, 0xe1, 0x4f, - 0x37, 0x14, 0x5f, 0xf2, 0x6d, 0x0a, 0x2b, 0x30, 0x1b, 0x43, 0x3a, 0xcd, 0xb3, 0x19, 0x95, 0xef, - 0xdd, 0x04, 0x34, 0x8e, 0x79, 0x08, 0x4a, 0x51, 0x22, 0x9b, 0x13, 0x3b, 0xa6, 0xbe, 0x0b, 0x02, - 0x74, 0xcc, 0x67, 0x8a, 0x08, 0x4e, 0x02, 0x29, 0xd1, 0x1c, 0xdc, 0x80, 0x8b, 0x62, 0xc6, 0xc4, - 0x34, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0x0f, 0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00 - }; + private static readonly BigInteger MoreModularExponentialGroup16Reversed = new BigInteger( + [ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x99, 0x31, 0x06, 0x34, 0xc9, 0x35, 0xf4, 0x4d, + 0x8f, 0xc0, 0xa6, 0x90, 0xdc, 0xb7, 0xff, 0x86, 0xc1, 0xdd, 0x8f, 0x8d, 0x98, 0xea, 0xb4, 0x93, + 0xa9, 0x5a, 0xb0, 0xd5, 0x27, 0x91, 0x06, 0xd0, 0x1c, 0x48, 0x70, 0x21, 0x76, 0xdd, 0x1b, 0xb8, + 0xaf, 0xd7, 0xe2, 0xce, 0x70, 0x29, 0x61, 0x1f, 0xed, 0xe7, 0x5b, 0x51, 0x86, 0xa1, 0x3b, 0x23, + 0xa2, 0xc3, 0x90, 0xa0, 0x4f, 0x96, 0xb2, 0x99, 0x5d, 0xc0, 0x6b, 0x4e, 0x47, 0x59, 0x7c, 0x28, + 0xa6, 0xca, 0xbe, 0x1f, 0x14, 0xfc, 0x8e, 0x2e, 0xf9, 0x8e, 0xde, 0x04, 0xdb, 0xc2, 0xbb, 0xdb, + 0xe8, 0x4c, 0xd4, 0x2a, 0xca, 0xe9, 0x83, 0x25, 0xda, 0x0b, 0x15, 0xb6, 0x34, 0x68, 0x94, 0x1a, + 0x3c, 0xe2, 0xf4, 0x6a, 0x18, 0x27, 0xc3, 0x99, 0x26, 0x5b, 0xba, 0xbd, 0x10, 0x9a, 0x71, 0x88, + 0xd7, 0xe6, 0x87, 0xa7, 0x12, 0x3c, 0x72, 0x1a, 0x01, 0x08, 0x21, 0xa9, 0x20, 0xd1, 0x82, 0x4b, + 0x8e, 0x10, 0xfd, 0xe0, 0xfc, 0x5b, 0xdb, 0x43, 0x31, 0xab, 0xe5, 0x74, 0xa0, 0x4f, 0xe2, 0x08, + 0xe2, 0x46, 0xd9, 0xba, 0xc0, 0x88, 0x09, 0x77, 0x6c, 0x5d, 0x61, 0x7a, 0x57, 0x17, 0xe1, 0xbb, + 0x0c, 0x20, 0x7b, 0x17, 0x18, 0x2b, 0x1f, 0x52, 0x64, 0x6a, 0xc8, 0x3e, 0x73, 0x02, 0x76, 0xd8, + 0x64, 0x08, 0x8a, 0xd9, 0x06, 0xfa, 0x2f, 0xf1, 0x6b, 0xee, 0xd2, 0x1a, 0x26, 0xd2, 0xe3, 0xce, + 0x9d, 0x61, 0x25, 0x4a, 0xe0, 0x94, 0x8c, 0x1e, 0xd7, 0x33, 0x09, 0xdb, 0x8c, 0xae, 0xf5, 0xab, + 0xc7, 0xe4, 0xe1, 0xa6, 0x85, 0x0f, 0x97, 0xb3, 0x7d, 0x0c, 0x06, 0x5d, 0x57, 0x71, 0xea, 0x8a, + 0x0a, 0xef, 0xdb, 0x58, 0x04, 0x85, 0xfb, 0xec, 0x64, 0xba, 0x1c, 0xdf, 0xab, 0x21, 0x55, 0xa8, + 0x33, 0x7a, 0x50, 0x04, 0x0d, 0x17, 0x33, 0xad, 0x2d, 0xc4, 0xaa, 0x8a, 0x5a, 0x8e, 0x72, 0x15, + 0x10, 0x05, 0xfa, 0x98, 0x18, 0x26, 0xd2, 0x15, 0xe5, 0x6a, 0x95, 0xea, 0x7c, 0x49, 0x95, 0x39, + 0x18, 0x17, 0x58, 0x95, 0xf6, 0xcb, 0x2b, 0xde, 0xc9, 0x52, 0x4c, 0x6f, 0xf0, 0x5d, 0xc5, 0xb5, + 0x8f, 0xa2, 0x07, 0xec, 0xa2, 0x83, 0x27, 0x9b, 0x03, 0x86, 0x0e, 0x18, 0x2c, 0x77, 0x9e, 0xe3, + 0x3b, 0xce, 0x36, 0x2e, 0x46, 0x5e, 0x90, 0x32, 0x7c, 0x21, 0x18, 0xca, 0x08, 0x6c, 0x74, 0xf1, + 0x04, 0x98, 0xbc, 0x4a, 0x4e, 0x35, 0x0c, 0x67, 0x6d, 0x96, 0x96, 0x70, 0x07, 0x29, 0xd5, 0x9e, + 0xbb, 0x52, 0x85, 0x20, 0x56, 0xf3, 0x62, 0x1c, 0x96, 0xad, 0xa3, 0xdc, 0x23, 0x5d, 0x65, 0x83, + 0x5f, 0xcf, 0x24, 0xfd, 0xa8, 0x3f, 0x16, 0x69, 0x9a, 0xd3, 0x55, 0x1c, 0x36, 0x48, 0xda, 0x98, + 0x05, 0xbf, 0x63, 0xa1, 0xb8, 0x7c, 0x00, 0xc2, 0x3d, 0x5b, 0xe4, 0xec, 0x51, 0x66, 0x28, 0x49, + 0xe6, 0x1f, 0x4b, 0x7c, 0x11, 0x24, 0x9f, 0xae, 0xa5, 0x9f, 0x89, 0x5a, 0xfb, 0x6b, 0x38, 0xee, + 0xed, 0xb7, 0x06, 0xf4, 0xb6, 0x5c, 0xff, 0x0b, 0x6b, 0xed, 0x37, 0xa6, 0xe9, 0x42, 0x4c, 0xf4, + 0xc6, 0x7e, 0x5e, 0x62, 0x76, 0xb5, 0x85, 0xe4, 0x45, 0xc2, 0x51, 0x6d, 0x6d, 0x35, 0xe1, 0x4f, + 0x37, 0x14, 0x5f, 0xf2, 0x6d, 0x0a, 0x2b, 0x30, 0x1b, 0x43, 0x3a, 0xcd, 0xb3, 0x19, 0x95, 0xef, + 0xdd, 0x04, 0x34, 0x8e, 0x79, 0x08, 0x4a, 0x51, 0x22, 0x9b, 0x13, 0x3b, 0xa6, 0xbe, 0x0b, 0x02, + 0x74, 0xcc, 0x67, 0x8a, 0x08, 0x4e, 0x02, 0x29, 0xd1, 0x1c, 0xdc, 0x80, 0x8b, 0x62, 0xc6, 0xc4, + 0x34, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0x0f, 0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00 + ]); public override BigInteger GroupPrime { get { - return new BigInteger(MoreModularExponentialGroup16Reversed); + return MoreModularExponentialGroup16Reversed; } } diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup1Sha1.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup1Sha1.cs index d0ff2c01d..1319c54df 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup1Sha1.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup1Sha1.cs @@ -1,4 +1,4 @@ -using Renci.SshNet.Common; +using System.Numerics; namespace Renci.SshNet.Security { @@ -7,21 +7,21 @@ namespace Renci.SshNet.Security /// internal sealed class KeyExchangeDiffieHellmanGroup1Sha1 : KeyExchangeDiffieHellmanGroupSha1 { - private static readonly byte[] SecondOkleyGroupReversed = - { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0x53, 0xe6, 0xec, - 0x51, 0x66, 0x28, 0x49, 0xe6, 0x1f, 0x4b, 0x7c, 0x11, 0x24, 0x9f, 0xae, - 0xa5, 0x9f, 0x89, 0x5a, 0xfb, 0x6b, 0x38, 0xee, 0xed, 0xb7, 0x06, 0xf4, - 0xb6, 0x5c, 0xff, 0x0b, 0x6b, 0xed, 0x37, 0xa6, 0xe9, 0x42, 0x4c, 0xf4, - 0xc6, 0x7e, 0x5e, 0x62, 0x76, 0xb5, 0x85, 0xe4, 0x45, 0xc2, 0x51, 0x6d, - 0x6d, 0x35, 0xe1, 0x4f, 0x37, 0x14, 0x5f, 0xf2, 0x6d, 0x0a, 0x2b, 0x30, - 0x1b, 0x43, 0x3a, 0xcd, 0xb3, 0x19, 0x95, 0xef, 0xdd, 0x04, 0x34, 0x8e, - 0x79, 0x08, 0x4a, 0x51, 0x22, 0x9b, 0x13, 0x3b, 0xa6, 0xbe, 0x0b, 0x02, - 0x74, 0xcc, 0x67, 0x8a, 0x08, 0x4e, 0x02, 0x29, 0xd1, 0x1c, 0xdc, 0x80, - 0x8b, 0x62, 0xc6, 0xc4, 0x34, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0x0f, 0xc9, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00 - }; + private static readonly BigInteger SecondOkleyGroupReversed = new BigInteger( + [ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0x53, 0xe6, 0xec, + 0x51, 0x66, 0x28, 0x49, 0xe6, 0x1f, 0x4b, 0x7c, 0x11, 0x24, 0x9f, 0xae, + 0xa5, 0x9f, 0x89, 0x5a, 0xfb, 0x6b, 0x38, 0xee, 0xed, 0xb7, 0x06, 0xf4, + 0xb6, 0x5c, 0xff, 0x0b, 0x6b, 0xed, 0x37, 0xa6, 0xe9, 0x42, 0x4c, 0xf4, + 0xc6, 0x7e, 0x5e, 0x62, 0x76, 0xb5, 0x85, 0xe4, 0x45, 0xc2, 0x51, 0x6d, + 0x6d, 0x35, 0xe1, 0x4f, 0x37, 0x14, 0x5f, 0xf2, 0x6d, 0x0a, 0x2b, 0x30, + 0x1b, 0x43, 0x3a, 0xcd, 0xb3, 0x19, 0x95, 0xef, 0xdd, 0x04, 0x34, 0x8e, + 0x79, 0x08, 0x4a, 0x51, 0x22, 0x9b, 0x13, 0x3b, 0xa6, 0xbe, 0x0b, 0x02, + 0x74, 0xcc, 0x67, 0x8a, 0x08, 0x4e, 0x02, 0x29, 0xd1, 0x1c, 0xdc, 0x80, + 0x8b, 0x62, 0xc6, 0xc4, 0x34, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0x0f, 0xc9, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00 + ]); /// /// Gets algorithm name. @@ -41,7 +41,7 @@ public override BigInteger GroupPrime { get { - return new BigInteger(SecondOkleyGroupReversed); + return SecondOkleyGroupReversed; } } } diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupShaBase.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupShaBase.cs index b0db30eaa..f4d64833f 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupShaBase.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupShaBase.cs @@ -1,4 +1,5 @@ -using Renci.SshNet.Common; +using System.Numerics; + using Renci.SshNet.Messages.Transport; namespace Renci.SshNet.Security @@ -23,7 +24,7 @@ public override void Start(Session session, KeyExchangeInitMessage message, bool Session.KeyExchangeDhReplyMessageReceived += Session_KeyExchangeDhReplyMessageReceived; _prime = GroupPrime; - _group = new BigInteger(new byte[] { 2 }); + _group = 2; PopulateClientExchangeValue(); diff --git a/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs b/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs index 551fb948d..87ae7879b 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs @@ -1,6 +1,4 @@ -using System; - -using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Agreement; using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.Parameters; @@ -104,7 +102,7 @@ private void HandleServerEcdhReply(byte[] hostKey, byte[] serverExchangeValue, b var k1 = new byte[_keyAgreement.AgreementSize]; _keyAgreement.CalculateAgreement(publicKey, k1, 0); - SharedKey = k1.ToBigInteger2().ToByteArray().Reverse(); + SharedKey = k1.ToBigInteger2().ToByteArray(isBigEndian: true); } } } diff --git a/src/Renci.SshNet/Security/KeyExchangeECDH.cs b/src/Renci.SshNet/Security/KeyExchangeECDH.cs index b5e887f60..294e8a833 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECDH.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECDH.cs @@ -93,7 +93,7 @@ private void HandleServerEcdhReply(byte[] hostKey, byte[] serverExchangeValue, b var agreement = _impl.CalculateAgreement(serverExchangeValue); - SharedKey = agreement.ToBigInteger2().ToByteArray().Reverse(); + SharedKey = agreement.ToBigInteger2().ToByteArray(isBigEndian: true); } /// diff --git a/src/Renci.SshNet/Security/SshKeyData.cs b/src/Renci.SshNet/Security/SshKeyData.cs index fa0671459..0a1467a52 100644 --- a/src/Renci.SshNet/Security/SshKeyData.cs +++ b/src/Renci.SshNet/Security/SshKeyData.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Numerics; using System.Text; using Org.BouncyCastle.Math.EC.Rfc8032; @@ -38,7 +39,7 @@ protected override int BufferCapacity foreach (var key in Keys) { capacity += 4; // Key length - capacity += key.BitLength / 8; // Key + capacity += (int)(key.GetBitLength() / 8); // Key } return capacity; @@ -86,7 +87,7 @@ protected override void SaveData() foreach (var key in Keys) { - var keyData = key.ToByteArray().Reverse(); + var keyData = key.ToByteArray(isBigEndian: true); if (Name == "ssh-ed25519") { keyData = keyData.TrimLeadingZeros().Pad(Ed25519.PublicKeySize); diff --git a/test/Renci.SshNet.Tests/Classes/Common/BigIntegerTest.cs b/test/Renci.SshNet.Tests/Classes/Common/BigIntegerTest.cs deleted file mode 100644 index f3786ece3..000000000 --- a/test/Renci.SshNet.Tests/Classes/Common/BigIntegerTest.cs +++ /dev/null @@ -1,1678 +0,0 @@ -// Based in huge part on: -// -// https://github.com/mono/mono/blob/master/mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs -// -// Authors: -// Rodrigo Kumpera -// -// Copyright (C) 2010 Novell, Inc (http://www.novell.com) -// - -//#define FEATURE_NUMERICS_BIGINTEGER - -using System; -using System.Globalization; -using System.Threading; - -using Microsoft.VisualStudio.TestTools.UnitTesting; - -using Renci.SshNet.Common; - -#if FEATURE_NUMERICS_BIGINTEGER -using BigInteger = System.Numerics.BigInteger; -#else -using BigInteger = Renci.SshNet.Common.BigInteger; -#endif - - -namespace Renci.SshNet.Tests.Classes.Common -{ - [TestClass] - public class BigIntegerTest - { - private static readonly byte[] Huge_a = - { - 0x1D, 0x33, 0xFB, 0xFE, 0xB1, 0x2, 0x85, 0x44, 0xCA, 0xDC, 0xFB, 0x70, 0xD, 0x39, - 0xB1, 0x47, 0xB6, 0xE6, 0xA2, 0xD1, 0x19, 0x1E, 0x9F, 0xE4, 0x3C, 0x1E, 0x16, 0x56, 0x13, 0x9C, 0x4D, 0xD3, - 0x5C, 0x74, 0xC9, 0xBD, 0xFA, 0x56, 0x40, 0x58, 0xAC, 0x20, 0x6B, 0x55, 0xA2, 0xD5, 0x41, 0x38, 0xA4, 0x6D, - 0xF6, 0x8C - }; - - private static readonly byte[] Huge_b = - { - 0x96, 0x5, 0xDA, 0xFE, 0x93, 0x17, 0xC1, 0x93, 0xEC, 0x2F, 0x30, 0x2D, 0x8F, - 0x28, 0x13, 0x99, 0x70, 0xF4, 0x4C, 0x60, 0xA6, 0x49, 0x24, 0xF9, 0xB3, 0x4A, 0x41, 0x67, 0xDC, 0xDD, 0xB1, - 0xA5, 0xA6, 0xC0, 0x3D, 0x57, 0x9A, 0xCB, 0x29, 0xE2, 0x94, 0xAC, 0x6C, 0x7D, 0xEF, 0x3E, 0xC6, 0x7A, 0xC1, - 0xA8, 0xC8, 0xB0, 0x20, 0x95, 0xE6, 0x4C, 0xE1, 0xE0, 0x4B, 0x49, 0xD5, 0x5A, 0xB7 - }; - - private static readonly byte[] Huge_add = - { - 0xB3, 0x38, 0xD5, 0xFD, 0x45, 0x1A, 0x46, 0xD8, 0xB6, 0xC, 0x2C, 0x9E, 0x9C, - 0x61, 0xC4, 0xE0, 0x26, 0xDB, 0xEF, 0x31, 0xC0, 0x67, 0xC3, 0xDD, 0xF0, 0x68, 0x57, 0xBD, 0xEF, 0x79, 0xFF, - 0x78, 0x3, 0x35, 0x7, 0x15, 0x95, 0x22, 0x6A, 0x3A, 0x41, 0xCD, 0xD7, 0xD2, 0x91, 0x14, 0x8, 0xB3, 0x65, - 0x16, 0xBF, 0x3D, 0x20, 0x95, 0xE6, 0x4C, 0xE1, 0xE0, 0x4B, 0x49, 0xD5, 0x5A, 0xB7 - }; - - private static readonly byte[] A_m_b = - { - 0x87, 0x2D, 0x21, 0x0, 0x1E, 0xEB, 0xC3, 0xB0, 0xDD, 0xAC, 0xCB, 0x43, 0x7E, 0x10, - 0x9E, 0xAE, 0x45, 0xF2, 0x55, 0x71, 0x73, 0xD4, 0x7A, 0xEB, 0x88, 0xD3, 0xD4, 0xEE, 0x36, 0xBE, 0x9B, 0x2D, - 0xB6, 0xB3, 0x8B, 0x66, 0x60, 0x8B, 0x16, 0x76, 0x17, 0x74, 0xFE, 0xD7, 0xB2, 0x96, 0x7B, 0xBD, 0xE2, 0xC4, - 0x2D, 0xDC, 0xDE, 0x6A, 0x19, 0xB3, 0x1E, 0x1F, 0xB4, 0xB6, 0x2A, 0xA5, 0x48 - }; - - private static readonly byte[] B_m_a = - { - 0x79, 0xD2, 0xDE, 0xFF, 0xE1, 0x14, 0x3C, 0x4F, 0x22, 0x53, 0x34, 0xBC, 0x81, - 0xEF, 0x61, 0x51, 0xBA, 0xD, 0xAA, 0x8E, 0x8C, 0x2B, 0x85, 0x14, 0x77, 0x2C, 0x2B, 0x11, 0xC9, 0x41, 0x64, - 0xD2, 0x49, 0x4C, 0x74, 0x99, 0x9F, 0x74, 0xE9, 0x89, 0xE8, 0x8B, 0x1, 0x28, 0x4D, 0x69, 0x84, 0x42, 0x1D, - 0x3B, 0xD2, 0x23, 0x21, 0x95, 0xE6, 0x4C, 0xE1, 0xE0, 0x4B, 0x49, 0xD5, 0x5A, 0xB7 - }; - - private static readonly byte[] Huge_mul = - { - 0xFE, 0x83, 0xE1, 0x9B, 0x8D, 0x61, 0x40, 0xD1, 0x60, 0x19, 0xBD, 0x38, 0xF0, - 0xFF, 0x90, 0xAE, 0xDD, 0xAE, 0x73, 0x2C, 0x20, 0x23, 0xCF, 0x6, 0x7A, 0xB4, 0x1C, 0xE7, 0xD9, 0x64, 0x96, - 0x2C, 0x87, 0x7E, 0x1D, 0xB3, 0x8F, 0xD4, 0x33, 0xBA, 0xF4, 0x22, 0xB4, 0xDB, 0xC0, 0x5B, 0xA5, 0x64, 0xA0, - 0xBC, 0xCA, 0x3E, 0x94, 0x95, 0xDA, 0x49, 0xE2, 0xA8, 0x33, 0xA2, 0x6A, 0x33, 0xB1, 0xF2, 0xEA, 0x99, 0x32, - 0xD0, 0xB2, 0xAE, 0x55, 0x75, 0xBD, 0x19, 0xFC, 0x9A, 0xEC, 0x54, 0x87, 0x2A, 0x6, 0xCC, 0x78, 0xDA, 0x88, - 0xBB, 0xAB, 0xA5, 0x47, 0xEF, 0xC7, 0x2B, 0xC7, 0x5B, 0x32, 0x31, 0xCD, 0xD9, 0x53, 0x96, 0x1A, 0x9D, 0x9A, - 0x57, 0x40, 0x51, 0xB6, 0x5D, 0xC, 0x17, 0xD1, 0x86, 0xE9, 0xA4, 0x20 - }; - - private static readonly byte[] Huge_div = { 0x0 }; - - private static readonly byte[] Huge_rem = - { - 0x1D, 0x33, 0xFB, 0xFE, 0xB1, 0x2, 0x85, 0x44, 0xCA, 0xDC, 0xFB, 0x70, 0xD, - 0x39, 0xB1, 0x47, 0xB6, 0xE6, 0xA2, 0xD1, 0x19, 0x1E, 0x9F, 0xE4, 0x3C, 0x1E, 0x16, 0x56, 0x13, 0x9C, 0x4D, - 0xD3, 0x5C, 0x74, 0xC9, 0xBD, 0xFA, 0x56, 0x40, 0x58, 0xAC, 0x20, 0x6B, 0x55, 0xA2, 0xD5, 0x41, 0x38, 0xA4, - 0x6D, 0xF6, 0x8C - }; - private static readonly byte[][] Add_a = { new byte[] { 1 }, new byte[] { 0xFF }, Huge_a }; - private static readonly byte[][] Add_b = { new byte[] { 1 }, new byte[] { 1 }, Huge_b }; - private static readonly byte[][] Add_c = { new byte[] { 2 }, new byte[] { 0 }, Huge_add }; - - private readonly NumberFormatInfo _nfi = NumberFormatInfo.InvariantInfo; - private NumberFormatInfo _nfiUser; - - [TestInitialize] - public void SetUpFixture() - { - _nfiUser = new NumberFormatInfo - { - CurrencyDecimalDigits = 3, - CurrencyDecimalSeparator = ":", - CurrencyGroupSeparator = "/", - CurrencyGroupSizes = new[] { 2, 1, 0 }, - CurrencyNegativePattern = 10, // n $- - CurrencyPositivePattern = 3, // n $ - CurrencySymbol = "XYZ", - PercentDecimalDigits = 1, - PercentDecimalSeparator = ";", - PercentGroupSeparator = "~", - PercentGroupSizes = new[] { 1 }, - PercentNegativePattern = 2, - PercentPositivePattern = 2, - PercentSymbol = "%%%", - NumberDecimalSeparator = "." - }; - } - - [TestMethod] - public void Mul() - { - long[] values = { -1000000000L, -1000, -1, 0, 1, 1000, 100000000L }; - - for (var i = 0; i < values.Length; ++i) - { - for (var j = 0; j < values.Length; ++j) - { - var a = new BigInteger(values[i]); - var b = new BigInteger(values[j]); - var c = a * b; - Assert.AreEqual(values[i] * values[j], (long)c, "#_" + i + "_" + j); - } - } - } - - [TestMethod] - public void TestHugeMul() - { - var a = new BigInteger(Huge_a); - var b = new BigInteger(Huge_b); - - Assert.IsTrue(Huge_mul.IsEqualTo((a * b).ToByteArray())); - } - - [TestMethod] - public void DivRem() - { - long[] values = { -10000000330L, -5000, -1, 0, 1, 1000, 333, 10234544400L }; - - for (var i = 0; i < values.Length; ++i) - { - for (var j = 0; j < values.Length; ++j) - { - if (values[j] == 0) - { - continue; - } - - var a = new BigInteger(values[i]); - var b = new BigInteger(values[j]); - var c = BigInteger.DivRem(a, b, out var d); - - Assert.AreEqual(values[i] / values[j], (long)c, "#a_" + i + "_" + j); - Assert.AreEqual(values[i] % values[j], (long)d, "#b_" + i + "_" + j); - } - } - } - - [TestMethod] - public void TestHugeDivRem() - { - var a = new BigInteger(Huge_a); - var b = new BigInteger(Huge_b); - var c = BigInteger.DivRem(a, b, out var d); - - AssertEqual(Huge_div, c.ToByteArray()); - AssertEqual(Huge_rem, d.ToByteArray()); - } - - [TestMethod] - public void Pow() - { - try - { - _ = BigInteger.Pow(1, -1); - Assert.Fail("#1"); - } - catch (ArgumentOutOfRangeException) { } - - Assert.AreEqual(1, (int)BigInteger.Pow(99999, 0), "#2"); - Assert.AreEqual(99999, (int)BigInteger.Pow(99999, 1), "#5"); - Assert.AreEqual(59049, (int)BigInteger.Pow(3, 10), "#4"); - Assert.AreEqual(177147, (int)BigInteger.Pow(3, 11), "#5"); - Assert.AreEqual(-177147, (int)BigInteger.Pow(-3, 11), "#6"); - } - - [TestMethod] - public void ModPow() - { - try - { - _ = BigInteger.ModPow(1, -1, 5); - Assert.Fail("#1"); - } - catch (ArgumentOutOfRangeException) { } - - try - { - _ = BigInteger.ModPow(1, 5, 0); - Assert.Fail("#2"); - } - catch (DivideByZeroException) { } - - Assert.AreEqual(4L, (long)BigInteger.ModPow(3, 2, 5), "#2"); - Assert.AreEqual(20L, (long)BigInteger.ModPow(555, 10, 71), "#3"); - Assert.AreEqual(20L, (long)BigInteger.ModPow(-555, 10, 71), "#3"); - Assert.AreEqual(-24L, (long)BigInteger.ModPow(-555, 11, 71), "#3"); - } - - [TestMethod] - public void GreatestCommonDivisor() - { - Assert.AreEqual(999999, (int)BigInteger.GreatestCommonDivisor(999999, 0), "#1"); - Assert.AreEqual(999999, (int)BigInteger.GreatestCommonDivisor(0, 999999), "#2"); - Assert.AreEqual(1, (int)BigInteger.GreatestCommonDivisor(999999, 1), "#3"); - Assert.AreEqual(1, (int)BigInteger.GreatestCommonDivisor(1, 999999), "#4"); - Assert.AreEqual(1, (int)BigInteger.GreatestCommonDivisor(1, 0), "#5"); - Assert.AreEqual(1, (int)BigInteger.GreatestCommonDivisor(0, 1), "#6"); - - Assert.AreEqual(1, (int)BigInteger.GreatestCommonDivisor(999999, -1), "#7"); - Assert.AreEqual(1, (int)BigInteger.GreatestCommonDivisor(-1, 999999), "#8"); - Assert.AreEqual(1, (int)BigInteger.GreatestCommonDivisor(-1, 0), "#9"); - Assert.AreEqual(1, (int)BigInteger.GreatestCommonDivisor(0, -1), "#10"); - - Assert.AreEqual(2, (int)BigInteger.GreatestCommonDivisor(12345678, 8765432), "#11"); - Assert.AreEqual(2, (int)BigInteger.GreatestCommonDivisor(-12345678, 8765432), "#12"); - Assert.AreEqual(2, (int)BigInteger.GreatestCommonDivisor(12345678, -8765432), "#13"); - Assert.AreEqual(2, (int)BigInteger.GreatestCommonDivisor(-12345678, -8765432), "#14"); - - Assert.AreEqual(40, (int)BigInteger.GreatestCommonDivisor(5581 * 40, 6671 * 40), "#15"); - - Assert.AreEqual(5, (int)BigInteger.GreatestCommonDivisor(-5, 0), "#16"); - Assert.AreEqual(5, (int)BigInteger.GreatestCommonDivisor(0, -5), "#17"); - } - - [TestMethod] - public void Log() - { - const double delta = 0.000000000000001d; - - Assert.AreEqual(double.NegativeInfinity, BigInteger.Log(0)); - Assert.AreEqual(0d, BigInteger.Log(1)); - Assert.AreEqual(double.NaN, BigInteger.Log(-1)); - Assert.AreEqual(2.3025850929940459d, BigInteger.Log(10), delta); - Assert.AreEqual(6.9077552789821368d, BigInteger.Log(1000), delta); - Assert.AreEqual(double.NaN, BigInteger.Log(-234)); - } - - [TestMethod] - public void LogN() - { - const double delta = 0.000000000000001d; - - Assert.AreEqual(double.NaN, BigInteger.Log(10, 1), "#1"); - Assert.AreEqual(double.NaN, BigInteger.Log(10, 0), "#2"); - Assert.AreEqual(double.NaN, BigInteger.Log(10, -1), "#3"); - - Assert.AreEqual(double.NaN, BigInteger.Log(10, double.NaN), "#4"); - Assert.AreEqual(double.NaN, BigInteger.Log(10, double.NegativeInfinity), "#5"); - Assert.AreEqual(double.NaN, BigInteger.Log(10, double.PositiveInfinity), "#6"); - - Assert.AreEqual(0d, BigInteger.Log(1, 0), "#7"); - Assert.AreEqual(double.NaN, BigInteger.Log(1, double.NegativeInfinity), "#8"); - Assert.AreEqual(0, BigInteger.Log(1, double.PositiveInfinity), "#9"); - Assert.AreEqual(double.NaN, BigInteger.Log(1, double.NaN), "#10"); - - Assert.AreEqual(-2.5129415947320606d, BigInteger.Log(10, 0.4), delta, "#11"); - } - - [TestMethod] - public void DivRemByZero() - { - try - { - _ = BigInteger.DivRem(100, 0, out var d); - Assert.Fail("#1"); - } - catch (DivideByZeroException) - { - } - } - - [TestMethod] - public void TestAdd() - { - for (var i = 0; i < Add_a.Length; ++i) - { - var a = new BigInteger(Add_a[i]); - var b = new BigInteger(Add_b[i]); - var c = new BigInteger(Add_c[i]); - - Assert.AreEqual(c, a + b, "#" + i + "a"); - Assert.AreEqual(c, b + a, "#" + i + "b"); - Assert.AreEqual(c, BigInteger.Add(a, b), "#" + i + "c"); - AssertEqual(Add_c[i], (a + b).ToByteArray()); - } - } - - [TestMethod] - public void TestAdd2() - { - long[] values = { -100000000000L, -1000, -1, 0, 1, 1000, 100000000000L }; - - for (var i = 0; i < values.Length; ++i) - { - for (var j = 0; j < values.Length; ++j) - { - var a = new BigInteger(values[i]); - var b = new BigInteger(values[j]); - var c = a + b; - Assert.AreEqual(values[i] + values[j], (long)c, "#_" + i + "_" + j); - } - } - } - - [TestMethod] - public void TestHugeSub() - { - var a = new BigInteger(Huge_a); - var b = new BigInteger(Huge_b); - - AssertEqual(A_m_b, (a - b).ToByteArray()); - AssertEqual(B_m_a, (b - a).ToByteArray()); - } - - [TestMethod] - public void TestSub() - { - long[] values = { -100000000000L, -1000, -1, 0, 1, 1000, 100000000000L }; - - for (var i = 0; i < values.Length; ++i) - { - for (var j = 0; j < values.Length; ++j) - { - var a = new BigInteger(values[i]); - var b = new BigInteger(values[j]); - var c = a - b; - var d = BigInteger.Subtract(a, b); - - Assert.AreEqual(values[i] - values[j], (long)c, "#_" + i + "_" + j); - Assert.AreEqual(values[i] - values[j], (long)d, "#_" + i + "_" + j); - } - } - } - - [TestMethod] - public void TestMin() - { - long[] values = { -100000000000L, -1000L, -1L, 0L, 1L, 1000L, 100000000000L }; - - for (var i = 0; i < values.Length; ++i) - { - for (var j = 0; j < values.Length; ++j) - { - var a = new BigInteger(values[i]); - var b = new BigInteger(values[j]); - var c = BigInteger.Min(a, b); - - Assert.AreEqual(Math.Min(values[i], values[j]), (long)c, "#_" + i + "_" + j); - } - } - } - - [TestMethod] - public void TestMax() - { - long[] values = { -100000000000L, -1000, -1, 0, 1, 1000, 100000000000L }; - - for (var i = 0; i < values.Length; ++i) - { - for (var j = 0; j < values.Length; ++j) - { - var a = new BigInteger(values[i]); - var b = new BigInteger(values[j]); - var c = BigInteger.Max(a, b); - - Assert.AreEqual(Math.Max(values[i], values[j]), (long)c, "#_" + i + "_" + j); - } - } - } - - [TestMethod] - public void TestAbs() - { - long[] values = { -100000000000L, -1000, -1, 0, 1, 1000, 100000000000L }; - - for (var i = 0; i < values.Length; ++i) - { - var a = new BigInteger(values[i]); - var c = BigInteger.Abs(a); - - Assert.AreEqual(Math.Abs(values[i]), (long)c, "#_" + i); - } - } - - [TestMethod] - public void TestNegate() - { - long[] values = { -100000000000L, -1000, -1, 0, 1, 1000, 100000000000L }; - - for (var i = 0; i < values.Length; ++i) - { - var a = new BigInteger(values[i]); - var c = -a; - var d = BigInteger.Negate(a); - - Assert.AreEqual(-values[i], (long)c, "#_" + i); - Assert.AreEqual(-values[i], (long)d, "#_" + i); - } - } - - [TestMethod] - public void TestInc() - { - long[] values = { -100000000000L, -1000, -1, 0, 1, 1000, 100000000000L }; - - for (var i = 0; i < values.Length; ++i) - { - var a = new BigInteger(values[i]); - var b = ++a; - - Assert.AreEqual(++values[i], (long)b, "#_" + i); - } - } - - [TestMethod] - public void TestDec() - { - long[] values = { -100000000000L, -1000, -1, 0, 1, 1000, 100000000000L }; - - for (var i = 0; i < values.Length; ++i) - { - var a = new BigInteger(values[i]); - var b = --a; - - Assert.AreEqual(--values[i], (long)b, "#_" + i); - } - } - - [TestMethod] - public void TestBitwiseOps() - { - long[] values = { -100000000000L, -1000, -1, 0, 1, 1000, 100000000000L, 0xFFFF00000000L }; - - for (var i = 0; i < values.Length; ++i) - { - for (var j = 0; j < values.Length; ++j) - { - var a = new BigInteger(values[i]); - var b = new BigInteger(values[j]); - - Assert.AreEqual(values[i] | values[j], (long)(a | b), "#b_" + i + "_" + j); - Assert.AreEqual(values[i] & values[j], (long)(a & b), "#a_" + i + "_" + j); - Assert.AreEqual(values[i] ^ values[j], (long)(a ^ b), "#c_" + i + "_" + j); - Assert.AreEqual(~values[i], (long)~a, "#d_" + i + "_" + j); - } - } - } - - [TestMethod] - public void TestLeftShift() - { - AssertEqual(new byte[] { 0x00, 0x28 }, (new BigInteger(0x0A) << 10).ToByteArray()); - AssertEqual(new byte[] { 0x00, 0xD8 }, (new BigInteger(-10) << 10).ToByteArray()); - AssertEqual(new byte[] { 0x00, 0x00, 0xFF }, (new BigInteger(-1) << 16).ToByteArray()); - AssertEqual(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A }, (new BigInteger(0x0A) << 80).ToByteArray()); - AssertEqual(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6 }, (new BigInteger(-10) << 80).ToByteArray()); - AssertEqual(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }, (new BigInteger(-1) << 80).ToByteArray()); - AssertEqual(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xD9 }, (new BigInteger(-1234) << 75).ToByteArray()); - AssertEqual(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x91, 0x00 }, (new BigInteger(0x1234) << 75).ToByteArray()); - AssertEqual(new byte[] { 0xFF, 0x00 }, (new BigInteger(0xFF00) << -8).ToByteArray()); - } - - [TestMethod] - public void TestRightShift() - { - AssertEqual(new byte[] { 0x16, 0xB0, 0x4C, 0x02 }, (new BigInteger(1234567899L) >> 5).ToByteArray()); - AssertEqual(new byte[] { 0x2C, 0x93, 0x00 }, (new BigInteger(1234567899L) >> 15).ToByteArray()); - AssertEqual(new byte[] { 0xFF, 0xFF, 0x7F }, (new BigInteger(long.MaxValue - 100) >> 40).ToByteArray()); - AssertEqual(new byte[] { 0xE9, 0x4F, 0xB3, 0xFD }, (new BigInteger(-1234567899L) >> 5).ToByteArray()); - AssertEqual(new byte[] { 0xD3, 0x6C, 0xFF }, (new BigInteger(-1234567899L) >> 15).ToByteArray()); - AssertEqual(new byte[] { 0x00, 0x00, 0x80 }, (new BigInteger(long.MinValue + 100) >> 40).ToByteArray()); - AssertEqual(new byte[] { 0xFF }, (new BigInteger(-1234567899L) >> 90).ToByteArray()); - AssertEqual(new byte[] { 0x00 }, (new BigInteger(999999) >> 90).ToByteArray()); - AssertEqual(new byte[] { 0x00, 0x00, 0xFF, 0x00 }, (new BigInteger(0xFF00) >> -8).ToByteArray()); - } - - [TestMethod] - public void CompareOps() - { - long[] values = { -100000000000L, -1000, -1, 0, 1, 1000, 100000000000L }; - - for (var i = 0; i < values.Length; ++i) - { - for (var j = 0; j < values.Length; ++j) - { - var a = new BigInteger(values[i]); - var b = new BigInteger(values[j]); - - Assert.AreEqual(values[i].CompareTo(values[j]), a.CompareTo(b), "#a_" + i + "_" + j); - Assert.AreEqual(values[i].CompareTo(values[j]), BigInteger.Compare(a, b), "#b_" + i + "_" + j); - - Assert.AreEqual(values[i] < values[j], a < b, "#c_" + i + "_" + j); - Assert.AreEqual(values[i] <= values[j], a <= b, "#d_" + i + "_" + j); - Assert.AreEqual(values[i] == values[j], a == b, "#e_" + i + "_" + j); - Assert.AreEqual(values[i] != values[j], a != b, "#f_" + i + "_" + j); - Assert.AreEqual(values[i] >= values[j], a >= b, "#g_" + i + "_" + j); - Assert.AreEqual(values[i] > values[j], a > b, "#h_" + i + "_" + j); - } - } - } - - [TestMethod] - public void CompareOps2() - { - var a = new BigInteger(100000000000L); - var b = new BigInteger(28282828282UL); - - Assert.IsTrue(a >= b, "#1"); - Assert.IsTrue(a >= b, "#2"); - Assert.IsFalse(a < b, "#3"); - Assert.IsFalse(a <= b, "#4"); - Assert.AreEqual(1, a.CompareTo(b), "#5"); - } - - [TestMethod] - public void CompareULong() - { - long[] values = { -100000000000L, -1000, -1, 0, 1, 1000, 100000000000L, 0xAA00000000L }; - ulong[] uvalues = { 0, 1, 1000, 100000000000L, 999999, 28282828282, 0xAA00000000, ulong.MaxValue }; - - for (var i = 0; i < values.Length; ++i) - { - for (var j = 0; j < uvalues.Length; ++j) - { - var a = new BigInteger(values[i]); - var b = uvalues[j]; - var c = new BigInteger(b); - - Assert.AreEqual(a.CompareTo(c), a.CompareTo(b), "#a_" + i + "_" + j); - - Assert.AreEqual(a > c, a > b, "#b_" + i + "_" + j); - Assert.AreEqual(a < c, a < b, "#c_" + i + "_" + j); - Assert.AreEqual(a <= c, a <= b, "#d_" + i + "_" + j); - Assert.AreEqual(a == c, a == b, "#e_" + i + "_" + j); - Assert.AreEqual(a != c, a != b, "#f_" + i + "_" + j); - Assert.AreEqual(a >= c, a >= b, "#g_" + i + "_" + j); - - Assert.AreEqual(c > a, b > a, "#ib_" + i + "_" + j); - Assert.AreEqual(c < a, b < a, "#ic_" + i + "_" + j); - Assert.AreEqual(c <= a, b <= a, "#id_" + i + "_" + j); - Assert.AreEqual(c == a, b == a, "#ie_" + i + "_" + j); - Assert.AreEqual(c != a, b != a, "#if_" + i + "_" + j); - Assert.AreEqual(c >= a, b >= a, "#ig_" + i + "_" + j); - } - } - } - - [TestMethod] - public void CompareLong() - { - long[] values = { -100000000000L, -1000, -1, 0, 1, 1000, 9999999, 100000000000L, 0xAA00000000, long.MaxValue, long.MinValue }; - - for (var i = 0; i < values.Length; ++i) - { - for (var j = 0; j < values.Length; ++j) - { - var a = new BigInteger(values[i]); - var b = values[j]; - var c = new BigInteger(b); - - Assert.AreEqual(a.CompareTo(c), a.CompareTo(b), "#a_" + i + "_" + j); - - Assert.AreEqual(a > c, a > b, "#b_" + i + "_" + j); - Assert.AreEqual(a < c, a < b, "#c_" + i + "_" + j); - Assert.AreEqual(a <= c, a <= b, "#d_" + i + "_" + j); - Assert.AreEqual(a == c, a == b, "#e_" + i + "_" + j); - Assert.AreEqual(a != c, a != b, "#f_" + i + "_" + j); - Assert.AreEqual(a >= c, a >= b, "#g_" + i + "_" + j); - - Assert.AreEqual(c > a, b > a, "#ib_" + i + "_" + j); - Assert.AreEqual(c < a, b < a, "#ic_" + i + "_" + j); - Assert.AreEqual(c <= a, b <= a, "#id_" + i + "_" + j); - Assert.AreEqual(c == a, b == a, "#ie_" + i + "_" + j); - Assert.AreEqual(c != a, b != a, "#if_" + i + "_" + j); - Assert.AreEqual(c >= a, b >= a, "#ig_" + i + "_" + j); - } - } - } - - [TestMethod] - public void TestEquals() - { - var a = new BigInteger(10); - var b = new BigInteger(10); - var c = new BigInteger(-10); - - Assert.AreEqual(a, b, "#1"); - Assert.AreNotEqual(a, c, "#2"); - Assert.AreEqual(a, 10, "#3"); - } - - [TestMethod] - public void Ctor_ByteArray_ShouldThrowArgumentNullExceptionWhenValueIsNull() - { - const byte[] value = null; - - try - { - var actual = new BigInteger(value); - Assert.Fail("#1:" + actual); - } - catch (ArgumentNullException ex) - { - Assert.IsNull(ex.InnerException); - Assert.AreEqual("value", ex.ParamName); - } - } - - [TestMethod] - public void ByteArrayCtor() - { - Assert.AreEqual(0, (int)new BigInteger(new byte[0])); - Assert.AreEqual(0, (int)new BigInteger(new byte[1])); - Assert.AreEqual(0, (int)new BigInteger(new byte[2])); - } - - [TestMethod] - public void IntCtorRoundTrip() - { - int[] values = - { - int.MinValue, -0x2F33BB, -0x1F33, -0x33, 0, 0x33, - 0x80, 0x8190, 0xFF0011, 0x1234, 0x11BB99, 0x44BB22CC, - int.MaxValue - }; - - foreach (var val in values) - { - var a = new BigInteger(val); - var b = new BigInteger(a.ToByteArray()); - - Assert.AreEqual(val, (int)a, "#a_" + val); - Assert.AreEqual(val, (int)b, "#b_" + val); - } - } - - [TestMethod] - public void LongCtorRoundTrip() - { - long[] values = - { - 0L, long.MinValue, long.MaxValue, -1, 1L + int.MaxValue, -1L + int.MinValue, 0x1234, 0xFFFFFFFFL, - 0x1FFFFFFFFL, -0xFFFFFFFFL, -0x1FFFFFFFFL, 0x100000000L, -0x100000000L, 0x100000001L, -0x100000001L, - 4294967295L, -4294967295L, 4294967296L, -4294967296L - }; - - foreach (var val in values) - { - try - { - var a = new BigInteger(val); - var b = new BigInteger(a.ToByteArray()); - - Assert.AreEqual(val, (long)a, "#a_" + val); - Assert.AreEqual(val, (long)b, "#b_" + val); - Assert.AreEqual(a, b, "#a == #b (" + val + ")"); - } - catch (Exception e) - { - Assert.Fail("Failed to roundtrip {0}: {1}", val, e); - } - } - } - - [TestMethod] - public void ByteArrayCtorRoundTrip() - { - var arr = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - AssertEqual(arr, new BigInteger(arr).ToByteArray()); - - arr = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 0xFF, 0x0 }; - AssertEqual(arr, new BigInteger(arr).ToByteArray()); - - arr = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xF0 }; - AssertEqual(arr, new BigInteger(arr).ToByteArray()); - - arr = new byte[] { 1 }; - AssertEqual(arr, new BigInteger(arr).ToByteArray()); - - arr = new byte[] { 1, 2 }; - AssertEqual(arr, new BigInteger(arr).ToByteArray()); - - arr = new byte[] { 1, 2, 3 }; - AssertEqual(arr, new BigInteger(arr).ToByteArray()); - - arr = new byte[] { 1, 2, 3, 4 }; - AssertEqual(arr, new BigInteger(arr).ToByteArray()); - - arr = new byte[] { 1, 2, 3, 4, 5 }; - AssertEqual(arr, new BigInteger(arr).ToByteArray()); - - arr = new byte[] { 1, 2, 3, 4, 5, 6 }; - AssertEqual(arr, new BigInteger(arr).ToByteArray()); - - arr = new byte[] { 1, 2, 3, 4, 5, 6, 7 }; - AssertEqual(arr, new BigInteger(arr).ToByteArray()); - - arr = new byte[] { 1, 2, 3, 4, 5 }; - AssertEqual(arr, new BigInteger(arr).ToByteArray()); - - arr = new byte[] { 0 }; - AssertEqual(arr, new BigInteger(arr).ToByteArray()); - - arr = new byte[] { 0xFF, 00 }; - AssertEqual(arr, new BigInteger(arr).ToByteArray()); - - arr = new byte[] { 1, 0, 0, 0, 0, 0 }; - AssertEqual(new byte[] { 1 }, new BigInteger(arr).ToByteArray()); - } - - [TestMethod] - public void TestIntCtorProperties() - { - var a = new BigInteger(10); - Assert.IsTrue(a.IsEven, "#1"); - Assert.IsFalse(a.IsOne, "#2"); - Assert.IsFalse(a.IsPowerOfTwo, "#3"); - Assert.IsFalse(a.IsZero, "#4"); - Assert.AreEqual(1, a.Sign, "#5"); - - Assert.IsFalse(new BigInteger(11).IsEven, "#6"); - Assert.IsTrue(new BigInteger(1).IsOne, "#7"); - Assert.IsTrue(new BigInteger(32).IsPowerOfTwo, "#8"); - Assert.IsTrue(new BigInteger(0).IsZero, "#9"); - Assert.IsTrue(new BigInteger().IsZero, "#9b"); - Assert.AreEqual(0, new BigInteger(0).Sign, "#10"); - Assert.AreEqual(-1, new BigInteger(-99999).Sign, "#11"); - - Assert.IsFalse(new BigInteger(0).IsPowerOfTwo, "#12"); - Assert.IsFalse(new BigInteger().IsPowerOfTwo, "#12b"); - Assert.IsFalse(new BigInteger(-16).IsPowerOfTwo, "#13"); - Assert.IsTrue(new BigInteger(1).IsPowerOfTwo, "#14"); - } - - [TestMethod] - public void TestIntCtorToString() - { - Assert.AreEqual("5555", new BigInteger(5555).ToString(), "#1"); - Assert.AreEqual("-99999", new BigInteger(-99999).ToString(), "#2"); - } - - [TestMethod] - public void TestToStringFmt() - { - Assert.AreEqual("123456789123456", new BigInteger(123456789123456).ToString("D2"), "#1"); - Assert.AreEqual("0000000005", new BigInteger(5).ToString("d10"), "#2"); - Assert.AreEqual("0A8", new BigInteger(168).ToString("X"), "#3"); - Assert.AreEqual("0", new BigInteger(0).ToString("X"), "#4"); - Assert.AreEqual("0", new BigInteger().ToString("X"), "#4b"); - Assert.AreEqual("1", new BigInteger(1).ToString("X"), "#5"); - Assert.AreEqual("0A", new BigInteger(10).ToString("X"), "#6"); - Assert.AreEqual("F6", new BigInteger(-10).ToString("X"), "#7"); - - Assert.AreEqual("10000000000000000000000000000000000000000000000000000000", BigInteger.Pow(10, 55).ToString("G"), "#8"); - - Assert.AreEqual("10000000000000000000000000000000000000000000000000000000", BigInteger.Pow(10, 55).ToString("R"), "#9"); - - - Assert.AreEqual("000000000A", new BigInteger(10).ToString("X10"), "#10"); - Assert.AreEqual("0000000010", new BigInteger(10).ToString("G10"), "#11"); - } - - [TestMethod] - public void TestToStringFmtProvider() - { - var info = new NumberFormatInfo - { - NegativeSign = ">", - PositiveSign = "%" - }; - - Assert.AreEqual("10", new BigInteger(10).ToString(info), "#1"); - Assert.AreEqual(">10", new BigInteger(-10).ToString(info), "#2"); - Assert.AreEqual("0A", new BigInteger(10).ToString("X", info), "#3"); - Assert.AreEqual("F6", new BigInteger(-10).ToString("X", info), "#4"); - Assert.AreEqual("10", new BigInteger(10).ToString("G", info), "#5"); - Assert.AreEqual(">10", new BigInteger(-10).ToString("G", info), "#6"); - Assert.AreEqual("10", new BigInteger(10).ToString("D", info), "#7"); - Assert.AreEqual(">10", new BigInteger(-10).ToString("D", info), "#8"); - Assert.AreEqual("10", new BigInteger(10).ToString("R", info), "#9"); - Assert.AreEqual(">10", new BigInteger(-10).ToString("R", info), "#10"); - - info = new NumberFormatInfo - { - NegativeSign = "#$%" - }; - - Assert.AreEqual("#$%10", new BigInteger(-10).ToString(info), "#2"); - Assert.AreEqual("#$%10", new BigInteger(-10).ToString(null, info), "#2"); - - info = new NumberFormatInfo(); - - Assert.AreEqual("-10", new BigInteger(-10).ToString(info), "#2"); - - } - - [TestMethod] - public void TestToIntOperator() - { - try - { - _ = (int)new BigInteger(Huge_a); - Assert.Fail("#1"); - } - catch (OverflowException) { } - - try - { - _ = (int)new BigInteger(1L + int.MaxValue); - Assert.Fail("#2"); - } - catch (OverflowException) { } - - try - { - _ = (int)new BigInteger(-1L + int.MinValue); - Assert.Fail("#3"); - } - catch (OverflowException) { } - - Assert.AreEqual(int.MaxValue, (int)new BigInteger(int.MaxValue), "#4"); - Assert.AreEqual(int.MinValue, (int)new BigInteger(int.MinValue), "#5"); - } - - - [TestMethod] - public void TestToLongOperator() - { - try - { - _ = (long)new BigInteger(Huge_a); - Assert.Fail("#1"); - } - catch (OverflowException) { } - - //long.MaxValue + 1 - try - { - _ = (long)new BigInteger(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 }); - Assert.Fail("#2"); - } - catch (OverflowException) { } - - //TODO long.MinValue - 1 - try - { - _ = (long)new BigInteger(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF }); - Assert.Fail("#3"); - } - catch (OverflowException) { } - - Assert.AreEqual(long.MaxValue, (long)new BigInteger(long.MaxValue), "#4"); - Assert.AreEqual(long.MinValue, (long)new BigInteger(long.MinValue), "#5"); - } - - [TestMethod] - public void TestIntCtorToByteArray() - { - AssertEqual(new byte[] { 0xFF }, new BigInteger(-1).ToByteArray()); - AssertEqual(new byte[] { 0xD4, 0xFE }, new BigInteger(-300).ToByteArray()); - AssertEqual(new byte[] { 0x80, 0x00 }, new BigInteger(128).ToByteArray()); - AssertEqual(new byte[] { 0x00, 0x60 }, new BigInteger(0x6000).ToByteArray()); - AssertEqual(new byte[] { 0x00, 0x80, 0x00 }, new BigInteger(0x8000).ToByteArray()); - AssertEqual(new byte[] { 0xDD, 0xBC, 0x00, 0x7A }, new BigInteger(0x7A00BCDD).ToByteArray()); - AssertEqual(new byte[] { 0xFF, 0xFF, 0xFF, 0x7F }, new BigInteger(int.MaxValue).ToByteArray()); - AssertEqual(new byte[] { 0x00, 0x00, 0x00, 0x80 }, new BigInteger(int.MinValue).ToByteArray()); - AssertEqual(new byte[] { 0x01, 0x00, 0x00, 0x80 }, new BigInteger(int.MinValue + 1).ToByteArray()); - AssertEqual(new byte[] { 0x7F }, new BigInteger(0x7F).ToByteArray()); - AssertEqual(new byte[] { 0x45, 0xCC, 0xD0 }, new BigInteger(-0x2F33BB).ToByteArray()); - AssertEqual(new byte[] { 0 }, new BigInteger(0).ToByteArray()); - AssertEqual(new byte[] { 0 }, new BigInteger().ToByteArray()); - } - - [TestMethod] - public void TestLongCtorToByteArray() - { - AssertEqual(new byte[] { 0x01 }, new BigInteger(0x01L).ToByteArray()); - AssertEqual(new byte[] { 0x02, 0x01 }, new BigInteger(0x0102L).ToByteArray()); - AssertEqual(new byte[] { 0x03, 0x02, 0x01 }, new BigInteger(0x010203L).ToByteArray()); - AssertEqual(new byte[] { 0x04, 0x03, 0x2, 0x01 }, new BigInteger(0x01020304L).ToByteArray()); - AssertEqual(new byte[] { 0x05, 0x04, 0x03, 0x2, 0x01 }, new BigInteger(0x0102030405L).ToByteArray()); - AssertEqual(new byte[] { 0x06, 0x05, 0x04, 0x03, 0x2, 0x01 }, new BigInteger(0x010203040506L).ToByteArray()); - AssertEqual(new byte[] { 0x07, 0x06, 0x05, 0x04, 0x03, 0x2, 0x01 }, new BigInteger(0x01020304050607L).ToByteArray()); - AssertEqual(new byte[] { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x2, 0x01 }, new BigInteger(0x0102030405060708L).ToByteArray()); - - AssertEqual(new byte[] { 0xFF }, new BigInteger(-0x01L).ToByteArray()); - AssertEqual(new byte[] { 0xFE, 0xFE }, new BigInteger(-0x0102L).ToByteArray()); - AssertEqual(new byte[] { 0xFD, 0xFD, 0xFE }, new BigInteger(-0x010203L).ToByteArray()); - AssertEqual(new byte[] { 0xFC, 0xFC, 0xFD, 0xFE }, new BigInteger(-0x01020304L).ToByteArray()); - AssertEqual(new byte[] { 0xFB, 0xFB, 0xFC, 0xFD, 0xFE }, new BigInteger(-0x0102030405L).ToByteArray()); - AssertEqual(new byte[] { 0xFA, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE }, new BigInteger(-0x010203040506L).ToByteArray()); - AssertEqual(new byte[] { 0xF9, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE }, new BigInteger(-0x01020304050607L).ToByteArray()); - AssertEqual(new byte[] { 0xF8, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE }, new BigInteger(-0x0102030405060708L).ToByteArray()); - - AssertEqual(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F }, new BigInteger(long.MaxValue).ToByteArray()); - AssertEqual(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }, new BigInteger(long.MinValue).ToByteArray()); - - AssertEqual(new byte[] { 0xFF, 0xFF, 0xFF, 0x7F, 0xFF }, new BigInteger(-2147483649L).ToByteArray()); - } - - [TestMethod] - public void CompareTo() - { - var a = new BigInteger(99); - Assert.AreEqual(-1, a.CompareTo(100), "#1"); - Assert.AreEqual(1, a.CompareTo(null), "#2"); - } - - [TestMethod] - public void ShortOperators() - { - Assert.AreEqual(22, (int)new BigInteger(22), "#1"); - Assert.AreEqual(-22, (int)new BigInteger(-22), "#2"); - - try - { - _ = (short)new BigInteger(10000000); - Assert.Fail("#3"); - } - catch (OverflowException) { } - - try - { - _ = (short)new BigInteger(-10000000); - Assert.Fail("#4"); - } - catch (OverflowException) { } - } - - [TestMethod] - public void Ctor_Double_NaN() - { - try - { - _ = new BigInteger(double.NaN); - Assert.Fail(); - } - catch (OverflowException) - { - } - } - - [TestMethod] - public void Ctor_Double_NegativeInfinity() - { - try - { - _ = new BigInteger(double.NegativeInfinity); - Assert.Fail(); - } - catch (OverflowException) - { - } - } - - [TestMethod] - public void Ctor_Double_PositiveInfinity() - { - try - { - _ = new BigInteger(double.PositiveInfinity); - Assert.Fail(); - } - catch (OverflowException) - { - } - } - - [TestMethod] - public void Ctor_Double() - { - Assert.AreEqual(10000, (int)new BigInteger(10000.2)); - Assert.AreEqual(10000, (int)new BigInteger(10000.9)); - Assert.AreEqual(10000, (int)new BigInteger(10000.2)); - Assert.AreEqual(0, (int)new BigInteger(0.9)); - Assert.AreEqual(12345678999L, (long)new BigInteger(12345678999.33)); - } - - [TestMethod] - public void DoubleConversion() - { - Assert.AreEqual(999d, (double)new BigInteger(999), "#1"); - Assert.AreEqual(double.PositiveInfinity, (double)BigInteger.Pow(2, 1024), "#2"); - Assert.AreEqual(double.NegativeInfinity, (double)BigInteger.Pow(-2, 1025), "#3"); - - Assert.AreEqual(0d, (double)BigInteger.Zero, "#4"); - Assert.AreEqual(1d, (double)BigInteger.One, "#5"); - Assert.AreEqual(-1d, (double)BigInteger.MinusOne, "#6"); - - var result1 = BitConverter.Int64BitsToDouble(-4337852273739220173); - Assert.AreEqual(result1, (double)new BigInteger(new byte[] { 53, 152, 137, 177, 240, 81, 75, 198 }), "#7"); - var result2 = BitConverter.Int64BitsToDouble(4893382453283402035); - Assert.AreEqual(result2, (double)new BigInteger(new byte[] { 53, 152, 137, 177, 240, 81, 75, 198, 0 }), "#8"); - - var result3 = BitConverter.Int64BitsToDouble(5010775143622804480); - var result4 = BitConverter.Int64BitsToDouble(5010775143622804481); - var result5 = BitConverter.Int64BitsToDouble(5010775143622804482); - Assert.AreEqual(result3, (double)new BigInteger(new byte[] { 0, 0, 0, 0, 16, 128, 208, 159, 60, 46, 59, 3 }), "#9"); - Assert.AreEqual(result3, (double)new BigInteger(new byte[] { 0, 0, 0, 0, 17, 128, 208, 159, 60, 46, 59, 3 }), "#10"); - Assert.AreEqual(result3, (double)new BigInteger(new byte[] { 0, 0, 0, 0, 24, 128, 208, 159, 60, 46, 59, 3 }), "#11"); - Assert.AreEqual(result4, (double)new BigInteger(new byte[] { 0, 0, 0, 0, 32, 128, 208, 159, 60, 46, 59, 3 }), "#12"); - Assert.AreEqual(result4, (double)new BigInteger(new byte[] { 0, 0, 0, 0, 48, 128, 208, 159, 60, 46, 59, 3 }), "#13"); - Assert.AreEqual(result5, (double)new BigInteger(new byte[] { 0, 0, 0, 0, 64, 128, 208, 159, 60, 46, 59, 3 }), "#14"); - - Assert.AreEqual(BitConverter.Int64BitsToDouble(-2748107935317889142), (double)new BigInteger(Huge_a), "#15"); - Assert.AreEqual(BitConverter.Int64BitsToDouble(-2354774254443231289), (double)new BigInteger(Huge_b), "#16"); - Assert.AreEqual(BitConverter.Int64BitsToDouble(8737073938546854790), (double)new BigInteger(Huge_mul), "#17"); - - Assert.AreEqual(BitConverter.Int64BitsToDouble(6912920136897069886), (double)(2278888483353476799 * BigInteger.Pow(2, 451)), "#18"); - Assert.AreEqual(double.PositiveInfinity, (double)(843942696292817306 * BigInteger.Pow(2, 965)), "#19"); - } - - [TestMethod] - public void DecimalCtor() - { - Assert.AreEqual(999, (int)new BigInteger(999.99m), "#1"); - Assert.AreEqual(-10000, (int)new BigInteger(-10000m), "#2"); - Assert.AreEqual(0, (int)new BigInteger(0m), "#3"); - } - - [TestMethod] - public void DecimalConversion() - { - Assert.AreEqual(999m, (decimal)new BigInteger(999), "#1"); - - try - { - var x = (decimal)BigInteger.Pow(2, 1024); - Assert.Fail("#2: " + x); - } - catch (OverflowException) - { - } - - try - { - var x = (decimal)BigInteger.Pow(-2, 1025); - Assert.Fail("#3: " + x); - } - catch (OverflowException) - { - } - - Assert.AreEqual(0m, (decimal)new BigInteger(0), "#4"); - Assert.AreEqual(1m, (decimal)new BigInteger(1), "#5"); - Assert.AreEqual(-1m, (decimal)new BigInteger(-1), "#6"); - Assert.AreEqual(9999999999999999999999999999m, (decimal)new BigInteger(9999999999999999999999999999m), "#7"); - Assert.AreEqual(0m, (decimal)new BigInteger(), "#8"); - } - - [TestMethod] - public void Parse() - { - try - { - _ = BigInteger.Parse(null); - Assert.Fail("#1"); - } - catch (ArgumentNullException) { } - - try - { - _ = BigInteger.Parse(""); - Assert.Fail("#2"); - } - catch (FormatException) { } - - - try - { - _ = BigInteger.Parse(" "); - Assert.Fail("#3"); - } - catch (FormatException) { } - - try - { - _ = BigInteger.Parse("hh"); - Assert.Fail("#4"); - } - catch (FormatException) { } - - try - { - _ = BigInteger.Parse("-"); - Assert.Fail("#5"); - } - catch (FormatException) { } - - try - { - _ = BigInteger.Parse("-+"); - Assert.Fail("#6"); - } - catch (FormatException) { } - - Assert.AreEqual(10, (int)BigInteger.Parse("+10"), "#7"); - Assert.AreEqual(10, (int)BigInteger.Parse("10 "), "#8"); - Assert.AreEqual(-10, (int)BigInteger.Parse("-10 "), "#9"); - Assert.AreEqual(10, (int)BigInteger.Parse(" 10 "), "#10"); - Assert.AreEqual(-10, (int)BigInteger.Parse(" -10 "), "#11"); - - Assert.AreEqual(-1, (int)BigInteger.Parse("F", NumberStyles.AllowHexSpecifier), "#12"); - Assert.AreEqual(-8, (int)BigInteger.Parse("8", NumberStyles.AllowHexSpecifier), "#13"); - Assert.AreEqual(8, (int)BigInteger.Parse("08", NumberStyles.AllowHexSpecifier), "#14"); - Assert.AreEqual(15, (int)BigInteger.Parse("0F", NumberStyles.AllowHexSpecifier), "#15"); - Assert.AreEqual(-1, (int)BigInteger.Parse("FF", NumberStyles.AllowHexSpecifier), "#16"); - Assert.AreEqual(255, (int)BigInteger.Parse("0FF", NumberStyles.AllowHexSpecifier), "#17"); - - Assert.AreEqual(-17, (int)BigInteger.Parse(" (17) ", NumberStyles.AllowParentheses | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite), "#18"); - Assert.AreEqual(-23, (int)BigInteger.Parse(" -23 ", NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite), "#19"); - - Assert.AreEqual(300000, (int)BigInteger.Parse("3E5", NumberStyles.AllowExponent), "#20"); - var dsep = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator; - Assert.AreEqual(250, (int)BigInteger.Parse("2" + dsep + "5E2", NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint), "#21");//2.5E2 = 250 - Assert.AreEqual(25, (int)BigInteger.Parse("2500E-2", NumberStyles.AllowExponent), "#22"); - - Assert.AreEqual("136236974127783066520110477975349088954559032721408", BigInteger.Parse("136236974127783066520110477975349088954559032721408", NumberStyles.None).ToString(), "#23"); - Assert.AreEqual("136236974127783066520110477975349088954559032721408", BigInteger.Parse("136236974127783066520110477975349088954559032721408").ToString(), "#24"); - - try - { - _ = BigInteger.Parse("2E3.0", NumberStyles.AllowExponent); // decimal notation for the exponent - Assert.Fail("#25"); - } - catch (FormatException) - { - } - - try - { - _ = int.Parse("2" + dsep + "09E1", NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent); - Assert.Fail("#26"); - } - catch (OverflowException) - { - } - } - - [TestMethod] - public void TryParse_Value_ShouldReturnFalseWhenValueIsNull() - { - var actual = BigInteger.TryParse(null, out var x); - - Assert.IsFalse(actual); - Assert.AreEqual(BigInteger.Zero, x); - } - - [TestMethod] - public void TryParse_Value() - { - Assert.IsFalse(BigInteger.TryParse("", out var x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsFalse(BigInteger.TryParse(" ", out x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsFalse(BigInteger.TryParse(" -", out x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsFalse(BigInteger.TryParse(" +", out x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsFalse(BigInteger.TryParse(" FF", out x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsTrue(BigInteger.TryParse(" 99", out x)); - Assert.AreEqual(99, (int)x); - - Assert.IsTrue(BigInteger.TryParse("+133", out x)); - Assert.AreEqual(133, (int)x); - - Assert.IsTrue(BigInteger.TryParse("-010", out x)); - Assert.AreEqual(-10, (int)x); - } - - [TestMethod] - public void TryParse_ValueAndStyleAndProvider() - { - Assert.IsFalse(BigInteger.TryParse("null", NumberStyles.None, null, out var x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsFalse(BigInteger.TryParse("-10", NumberStyles.None, null, out x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsFalse(BigInteger.TryParse("(10)", NumberStyles.None, null, out x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsFalse(BigInteger.TryParse(" 10", NumberStyles.None, null, out x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsFalse(BigInteger.TryParse("10 ", NumberStyles.None, null, out x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsTrue(BigInteger.TryParse("-10", NumberStyles.AllowLeadingSign, null, out x)); - Assert.AreEqual(-10, (int)x); - - Assert.IsTrue(BigInteger.TryParse("(10)", NumberStyles.AllowParentheses, null, out x)); - Assert.AreEqual(-10, (int)x); - - Assert.IsTrue(BigInteger.TryParse(" 10", NumberStyles.AllowLeadingWhite, null, out x)); - Assert.AreEqual(10, (int)x); - - Assert.IsTrue(BigInteger.TryParse("10 ", NumberStyles.AllowTrailingWhite, null, out x)); - Assert.AreEqual(10, (int)x); - - Assert.IsFalse(BigInteger.TryParse("$10", NumberStyles.None, null, out x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsFalse(BigInteger.TryParse("$10", NumberStyles.None, _nfi, out x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsFalse(BigInteger.TryParse("%10", NumberStyles.None, _nfi, out x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsFalse(BigInteger.TryParse("10 ", NumberStyles.None, null, out x)); - Assert.AreEqual(BigInteger.Zero, x); - - Assert.IsTrue(BigInteger.TryParse("10", NumberStyles.None, null, out x)); - Assert.AreEqual(10, (int)x); - - Assert.IsTrue(BigInteger.TryParse(_nfi.CurrencySymbol + "10", NumberStyles.AllowCurrencySymbol, _nfi, out x)); - Assert.AreEqual(10, (int)x); - - Assert.IsFalse(BigInteger.TryParse("%10", NumberStyles.AllowCurrencySymbol, _nfi, out x)); - Assert.AreEqual(BigInteger.Zero, x); - } - - [TestMethod] - public void TryParse_ValueAndStyleAndProvider_ShouldReturnFalseWhenValueIsNull() - { - var actual = BigInteger.TryParse(null, NumberStyles.Any, CultureInfo.InvariantCulture, out var x); - - Assert.IsFalse(actual); - Assert.AreEqual(BigInteger.Zero, x); - } - - [TestMethod] - public void TestUserCurrency() - { - const int val1 = -1234567; - const int val2 = 1234567; - - var s = val1.ToString("c", _nfiUser); - Assert.AreEqual("1234/5/67:000 XYZ-", s, "Currency value type 1 is not what we want to try to parse"); - - var v = BigInteger.Parse("1234/5/67:000 XYZ-", NumberStyles.Currency, _nfiUser); - Assert.AreEqual(val1, (int)v); - - s = val2.ToString("c", _nfiUser); - Assert.AreEqual("1234/5/67:000 XYZ", s, "Currency value type 2 is not what we want to try to parse"); - - v = BigInteger.Parse(s, NumberStyles.Currency, _nfiUser); - Assert.AreEqual(val2, (int)v); - } - - [TestMethod] - public void TryParseWeirdCulture() - { - var old = Thread.CurrentThread.CurrentCulture; - var cur = (CultureInfo)old.Clone(); - cur.NumberFormat = new NumberFormatInfo - { - NegativeSign = ">", - PositiveSign = "%" - }; - - Thread.CurrentThread.CurrentCulture = cur; - - try - { - Assert.IsTrue(BigInteger.TryParse("%11", out var x)); - Assert.AreEqual(11, (int)x); - - Assert.IsTrue(BigInteger.TryParse(">11", out x)); - Assert.AreEqual(-11, (int)x); - } - finally - { - Thread.CurrentThread.CurrentCulture = old; - } - } - - [TestMethod] - public void CompareToLongToWithBigNumber() - { - var a = BigInteger.Parse("123456789123456789"); - Assert.AreEqual(1, a.CompareTo(2000)); - Assert.AreEqual(1, a.CompareTo(-2000)); - - var b = BigInteger.Parse("-123456789123456789"); - Assert.AreEqual(-1, b.CompareTo(2000)); - Assert.AreEqual(-1, b.CompareTo(-2000)); - } - - [TestMethod] - public void LeftShiftByInt() - { - var v = BigInteger.Parse("230794411440927908251127453634"); - - Assert.AreEqual("230794411440927908251127453634", (v << 0).ToString(), "#0"); - Assert.AreEqual("461588822881855816502254907268", (v << 1).ToString(), "#1"); - Assert.AreEqual("923177645763711633004509814536", (v << 2).ToString(), "#2"); - Assert.AreEqual("1846355291527423266009019629072", (v << 3).ToString(), "#3"); - Assert.AreEqual("3692710583054846532018039258144", (v << 4).ToString(), "#4"); - Assert.AreEqual("7385421166109693064036078516288", (v << 5).ToString(), "#5"); - Assert.AreEqual("14770842332219386128072157032576", (v << 6).ToString(), "#6"); - Assert.AreEqual("29541684664438772256144314065152", (v << 7).ToString(), "#7"); - Assert.AreEqual("59083369328877544512288628130304", (v << 8).ToString(), "#8"); - Assert.AreEqual("118166738657755089024577256260608", (v << 9).ToString(), "#9"); - Assert.AreEqual("236333477315510178049154512521216", (v << 10).ToString(), "#10"); - Assert.AreEqual("472666954631020356098309025042432", (v << 11).ToString(), "#11"); - Assert.AreEqual("945333909262040712196618050084864", (v << 12).ToString(), "#12"); - Assert.AreEqual("1890667818524081424393236100169728", (v << 13).ToString(), "#13"); - Assert.AreEqual("3781335637048162848786472200339456", (v << 14).ToString(), "#14"); - Assert.AreEqual("7562671274096325697572944400678912", (v << 15).ToString(), "#15"); - Assert.AreEqual("15125342548192651395145888801357824", (v << 16).ToString(), "#16"); - Assert.AreEqual("30250685096385302790291777602715648", (v << 17).ToString(), "#17"); - Assert.AreEqual("60501370192770605580583555205431296", (v << 18).ToString(), "#18"); - Assert.AreEqual("121002740385541211161167110410862592", (v << 19).ToString(), "#19"); - Assert.AreEqual("242005480771082422322334220821725184", (v << 20).ToString(), "#20"); - Assert.AreEqual("484010961542164844644668441643450368", (v << 21).ToString(), "#21"); - Assert.AreEqual("968021923084329689289336883286900736", (v << 22).ToString(), "#22"); - Assert.AreEqual("1936043846168659378578673766573801472", (v << 23).ToString(), "#23"); - Assert.AreEqual("3872087692337318757157347533147602944", (v << 24).ToString(), "#24"); - Assert.AreEqual("7744175384674637514314695066295205888", (v << 25).ToString(), "#25"); - Assert.AreEqual("15488350769349275028629390132590411776", (v << 26).ToString(), "#26"); - Assert.AreEqual("30976701538698550057258780265180823552", (v << 27).ToString(), "#27"); - Assert.AreEqual("61953403077397100114517560530361647104", (v << 28).ToString(), "#28"); - Assert.AreEqual("123906806154794200229035121060723294208", (v << 29).ToString(), "#29"); - Assert.AreEqual("247813612309588400458070242121446588416", (v << 30).ToString(), "#30"); - Assert.AreEqual("495627224619176800916140484242893176832", (v << 31).ToString(), "#31"); - Assert.AreEqual("991254449238353601832280968485786353664", (v << 32).ToString(), "#32"); - Assert.AreEqual("1982508898476707203664561936971572707328", (v << 33).ToString(), "#33"); - Assert.AreEqual("3965017796953414407329123873943145414656", (v << 34).ToString(), "#34"); - Assert.AreEqual("7930035593906828814658247747886290829312", (v << 35).ToString(), "#35"); - Assert.AreEqual("15860071187813657629316495495772581658624", (v << 36).ToString(), "#36"); - Assert.AreEqual("31720142375627315258632990991545163317248", (v << 37).ToString(), "#37"); - Assert.AreEqual("63440284751254630517265981983090326634496", (v << 38).ToString(), "#38"); - Assert.AreEqual("126880569502509261034531963966180653268992", (v << 39).ToString(), "#39"); - Assert.AreEqual("253761139005018522069063927932361306537984", (v << 40).ToString(), "#40"); - Assert.AreEqual("507522278010037044138127855864722613075968", (v << 41).ToString(), "#41"); - Assert.AreEqual("1015044556020074088276255711729445226151936", (v << 42).ToString(), "#42"); - Assert.AreEqual("2030089112040148176552511423458890452303872", (v << 43).ToString(), "#43"); - Assert.AreEqual("4060178224080296353105022846917780904607744", (v << 44).ToString(), "#44"); - Assert.AreEqual("8120356448160592706210045693835561809215488", (v << 45).ToString(), "#45"); - Assert.AreEqual("16240712896321185412420091387671123618430976", (v << 46).ToString(), "#46"); - Assert.AreEqual("32481425792642370824840182775342247236861952", (v << 47).ToString(), "#47"); - Assert.AreEqual("64962851585284741649680365550684494473723904", (v << 48).ToString(), "#48"); - Assert.AreEqual("129925703170569483299360731101368988947447808", (v << 49).ToString(), "#49"); - Assert.AreEqual("259851406341138966598721462202737977894895616", (v << 50).ToString(), "#50"); - Assert.AreEqual("519702812682277933197442924405475955789791232", (v << 51).ToString(), "#51"); - Assert.AreEqual("1039405625364555866394885848810951911579582464", (v << 52).ToString(), "#52"); - Assert.AreEqual("2078811250729111732789771697621903823159164928", (v << 53).ToString(), "#53"); - Assert.AreEqual("4157622501458223465579543395243807646318329856", (v << 54).ToString(), "#54"); - Assert.AreEqual("8315245002916446931159086790487615292636659712", (v << 55).ToString(), "#55"); - Assert.AreEqual("16630490005832893862318173580975230585273319424", (v << 56).ToString(), "#56"); - Assert.AreEqual("33260980011665787724636347161950461170546638848", (v << 57).ToString(), "#57"); - Assert.AreEqual("66521960023331575449272694323900922341093277696", (v << 58).ToString(), "#58"); - Assert.AreEqual("133043920046663150898545388647801844682186555392", (v << 59).ToString(), "#59"); - Assert.AreEqual("266087840093326301797090777295603689364373110784", (v << 60).ToString(), "#60"); - Assert.AreEqual("532175680186652603594181554591207378728746221568", (v << 61).ToString(), "#61"); - Assert.AreEqual("1064351360373305207188363109182414757457492443136", (v << 62).ToString(), "#62"); - Assert.AreEqual("2128702720746610414376726218364829514914984886272", (v << 63).ToString(), "#63"); - Assert.AreEqual("4257405441493220828753452436729659029829969772544", (v << 64).ToString(), "#64"); - Assert.AreEqual("8514810882986441657506904873459318059659939545088", (v << 65).ToString(), "#65"); - Assert.AreEqual("17029621765972883315013809746918636119319879090176", (v << 66).ToString(), "#66"); - Assert.AreEqual("34059243531945766630027619493837272238639758180352", (v << 67).ToString(), "#67"); - Assert.AreEqual("68118487063891533260055238987674544477279516360704", (v << 68).ToString(), "#68"); - Assert.AreEqual("136236974127783066520110477975349088954559032721408", (v << 69).ToString(), "#69"); - } - - - [TestMethod] - public void RightShiftByInt() - { - var v = BigInteger.Parse("230794411440927908251127453634"); - v *= BigInteger.Pow(2, 70); - - Assert.AreEqual("272473948255566133040220955950698177909118065442816", (v >> 0).ToString(), "#0"); - Assert.AreEqual("136236974127783066520110477975349088954559032721408", (v >> 1).ToString(), "#1"); - Assert.AreEqual("68118487063891533260055238987674544477279516360704", (v >> 2).ToString(), "#2"); - Assert.AreEqual("34059243531945766630027619493837272238639758180352", (v >> 3).ToString(), "#3"); - Assert.AreEqual("17029621765972883315013809746918636119319879090176", (v >> 4).ToString(), "#4"); - Assert.AreEqual("8514810882986441657506904873459318059659939545088", (v >> 5).ToString(), "#5"); - Assert.AreEqual("4257405441493220828753452436729659029829969772544", (v >> 6).ToString(), "#6"); - Assert.AreEqual("2128702720746610414376726218364829514914984886272", (v >> 7).ToString(), "#7"); - Assert.AreEqual("1064351360373305207188363109182414757457492443136", (v >> 8).ToString(), "#8"); - Assert.AreEqual("532175680186652603594181554591207378728746221568", (v >> 9).ToString(), "#9"); - Assert.AreEqual("266087840093326301797090777295603689364373110784", (v >> 10).ToString(), "#10"); - Assert.AreEqual("133043920046663150898545388647801844682186555392", (v >> 11).ToString(), "#11"); - Assert.AreEqual("66521960023331575449272694323900922341093277696", (v >> 12).ToString(), "#12"); - Assert.AreEqual("33260980011665787724636347161950461170546638848", (v >> 13).ToString(), "#13"); - Assert.AreEqual("16630490005832893862318173580975230585273319424", (v >> 14).ToString(), "#14"); - Assert.AreEqual("8315245002916446931159086790487615292636659712", (v >> 15).ToString(), "#15"); - Assert.AreEqual("4157622501458223465579543395243807646318329856", (v >> 16).ToString(), "#16"); - Assert.AreEqual("2078811250729111732789771697621903823159164928", (v >> 17).ToString(), "#17"); - Assert.AreEqual("1039405625364555866394885848810951911579582464", (v >> 18).ToString(), "#18"); - Assert.AreEqual("519702812682277933197442924405475955789791232", (v >> 19).ToString(), "#19"); - Assert.AreEqual("259851406341138966598721462202737977894895616", (v >> 20).ToString(), "#20"); - Assert.AreEqual("129925703170569483299360731101368988947447808", (v >> 21).ToString(), "#21"); - Assert.AreEqual("64962851585284741649680365550684494473723904", (v >> 22).ToString(), "#22"); - Assert.AreEqual("32481425792642370824840182775342247236861952", (v >> 23).ToString(), "#23"); - Assert.AreEqual("16240712896321185412420091387671123618430976", (v >> 24).ToString(), "#24"); - Assert.AreEqual("8120356448160592706210045693835561809215488", (v >> 25).ToString(), "#25"); - Assert.AreEqual("4060178224080296353105022846917780904607744", (v >> 26).ToString(), "#26"); - Assert.AreEqual("2030089112040148176552511423458890452303872", (v >> 27).ToString(), "#27"); - Assert.AreEqual("1015044556020074088276255711729445226151936", (v >> 28).ToString(), "#28"); - Assert.AreEqual("507522278010037044138127855864722613075968", (v >> 29).ToString(), "#29"); - Assert.AreEqual("253761139005018522069063927932361306537984", (v >> 30).ToString(), "#30"); - Assert.AreEqual("126880569502509261034531963966180653268992", (v >> 31).ToString(), "#31"); - Assert.AreEqual("63440284751254630517265981983090326634496", (v >> 32).ToString(), "#32"); - Assert.AreEqual("31720142375627315258632990991545163317248", (v >> 33).ToString(), "#33"); - Assert.AreEqual("15860071187813657629316495495772581658624", (v >> 34).ToString(), "#34"); - Assert.AreEqual("7930035593906828814658247747886290829312", (v >> 35).ToString(), "#35"); - Assert.AreEqual("3965017796953414407329123873943145414656", (v >> 36).ToString(), "#36"); - Assert.AreEqual("1982508898476707203664561936971572707328", (v >> 37).ToString(), "#37"); - Assert.AreEqual("991254449238353601832280968485786353664", (v >> 38).ToString(), "#38"); - Assert.AreEqual("495627224619176800916140484242893176832", (v >> 39).ToString(), "#39"); - Assert.AreEqual("247813612309588400458070242121446588416", (v >> 40).ToString(), "#40"); - Assert.AreEqual("123906806154794200229035121060723294208", (v >> 41).ToString(), "#41"); - Assert.AreEqual("61953403077397100114517560530361647104", (v >> 42).ToString(), "#42"); - Assert.AreEqual("30976701538698550057258780265180823552", (v >> 43).ToString(), "#43"); - Assert.AreEqual("15488350769349275028629390132590411776", (v >> 44).ToString(), "#44"); - Assert.AreEqual("7744175384674637514314695066295205888", (v >> 45).ToString(), "#45"); - Assert.AreEqual("3872087692337318757157347533147602944", (v >> 46).ToString(), "#46"); - Assert.AreEqual("1936043846168659378578673766573801472", (v >> 47).ToString(), "#47"); - Assert.AreEqual("968021923084329689289336883286900736", (v >> 48).ToString(), "#48"); - Assert.AreEqual("484010961542164844644668441643450368", (v >> 49).ToString(), "#49"); - Assert.AreEqual("242005480771082422322334220821725184", (v >> 50).ToString(), "#50"); - Assert.AreEqual("121002740385541211161167110410862592", (v >> 51).ToString(), "#51"); - Assert.AreEqual("60501370192770605580583555205431296", (v >> 52).ToString(), "#52"); - Assert.AreEqual("30250685096385302790291777602715648", (v >> 53).ToString(), "#53"); - Assert.AreEqual("15125342548192651395145888801357824", (v >> 54).ToString(), "#54"); - Assert.AreEqual("7562671274096325697572944400678912", (v >> 55).ToString(), "#55"); - Assert.AreEqual("3781335637048162848786472200339456", (v >> 56).ToString(), "#56"); - Assert.AreEqual("1890667818524081424393236100169728", (v >> 57).ToString(), "#57"); - Assert.AreEqual("945333909262040712196618050084864", (v >> 58).ToString(), "#58"); - Assert.AreEqual("472666954631020356098309025042432", (v >> 59).ToString(), "#59"); - Assert.AreEqual("236333477315510178049154512521216", (v >> 60).ToString(), "#60"); - Assert.AreEqual("118166738657755089024577256260608", (v >> 61).ToString(), "#61"); - Assert.AreEqual("59083369328877544512288628130304", (v >> 62).ToString(), "#62"); - Assert.AreEqual("29541684664438772256144314065152", (v >> 63).ToString(), "#63"); - Assert.AreEqual("14770842332219386128072157032576", (v >> 64).ToString(), "#64"); - Assert.AreEqual("7385421166109693064036078516288", (v >> 65).ToString(), "#65"); - Assert.AreEqual("3692710583054846532018039258144", (v >> 66).ToString(), "#66"); - Assert.AreEqual("1846355291527423266009019629072", (v >> 67).ToString(), "#67"); - Assert.AreEqual("923177645763711633004509814536", (v >> 68).ToString(), "#68"); - Assert.AreEqual("461588822881855816502254907268", (v >> 69).ToString(), "#69"); - } - - [TestMethod] - public void Bug10887() - { - BigInteger b = 0; - for (var i = 1; i <= 16; i++) - { - b = (b * 256) + i; - } - - var p = BigInteger.Pow(2, 32); - - Assert.AreEqual("1339673755198158349044581307228491536", b.ToString()); - Assert.AreEqual("1339673755198158349044581307228491536", ((b << 32) / p).ToString()); - Assert.AreEqual("1339673755198158349044581307228491536", ((b * p) >> 32).ToString()); - } - - [TestMethod] - public void DefaultCtorWorks() - { - var a = new BigInteger(); - Assert.AreEqual(BigInteger.One, ++a, "#1"); - - a = new BigInteger(); - Assert.AreEqual(BigInteger.MinusOne, --a, "#2"); - - a = new BigInteger(); - Assert.AreEqual(BigInteger.MinusOne, ~a, "#3"); - - a = new BigInteger(); - Assert.AreEqual("0", a.ToString(), "#4"); - - a = new BigInteger(); -#pragma warning disable CS1718 // Comparison made to same variable - Assert.AreEqual(true, a == a, "#5"); - - a = new BigInteger(); - Assert.AreEqual(false, a < a, "#6"); -#pragma warning restore CS1718 // Comparison made to same variable - - a = new BigInteger(); - Assert.AreEqual(true, a < 10L, "#7"); - - a = new BigInteger(); - Assert.AreEqual(true, a.IsEven, "#8"); - - a = new BigInteger(); - Assert.AreEqual(0, (int)a, "#9"); - - a = new BigInteger(); - Assert.AreEqual((uint)0, (uint)a, "#10"); - - a = new BigInteger(); - Assert.AreEqual((ulong)0, (ulong)a, "#11"); - - a = new BigInteger(); - Assert.AreEqual(true, a.Equals(a), "#12"); - - a = new BigInteger(); - Assert.AreEqual(a, BigInteger.Min(a, a), "#13"); - - a = new BigInteger(); - Assert.AreEqual(a, BigInteger.GreatestCommonDivisor(a, a), "#14"); - - a = new BigInteger(); - Assert.AreEqual(BigInteger.Zero.GetHashCode(), a.GetHashCode(), "#15"); - - a = new BigInteger(); - Assert.AreEqual(BigInteger.Zero, a, "#16"); - } - - [TestMethod] - public void Bug16526() - { - var x = BigInteger.Pow(2, 63); - x *= -1; - x -= 1; - Assert.AreEqual("-9223372036854775809", x.ToString(), "#1"); - try - { - x = (long)x; - Assert.Fail("#2 Must OVF: " + x); - } - catch (OverflowException) - { - } - } - - [TestMethod] - public void MinusOne() - { - var minusOne = BigInteger.MinusOne; - - Assert.IsFalse(minusOne.IsEven); - Assert.IsFalse(minusOne.IsOne); - Assert.IsFalse(minusOne.IsPowerOfTwo); - Assert.IsFalse(minusOne.IsZero); - Assert.AreEqual(-1, minusOne.Sign); - } - - [TestMethod] - public void One() - { - var one = BigInteger.One; - - Assert.IsFalse(one.IsEven); - Assert.IsTrue(one.IsOne); - Assert.IsTrue(one.IsPowerOfTwo); - Assert.IsFalse(one.IsZero); - Assert.AreEqual(1, one.Sign); - } - - [TestMethod] - public void Zero() - { - var zero = BigInteger.Zero; - - Assert.IsTrue(zero.IsEven); - Assert.IsFalse(zero.IsOne); - Assert.IsFalse(zero.IsPowerOfTwo); - Assert.IsTrue(zero.IsZero); - Assert.AreEqual(0, zero.Sign); - } - - [TestMethod] - public void Random() - { - var max = "26432534714839143538998938508341375449389492936207135611931371046236385860280414659368073862189301615603000443463893527273703804361856647266218472759410964268979057798543462774631912259980510080575520846081682603934587649566608158932346151315049355432937004801361578344502537300865702429436253728164365180058583916866804254965536833106467354901266304654706123552932560896874808786957654734387252964281680963136344135750381838556467139236094522411774117748615141352874979928570068255439327082539676660277104989857941859821396157749462154431239343148671646397611770487668571604363151098131876313773395912355145689712506"; - Assert.IsTrue(BigInteger.TryParse(max, NumberStyles.Number, NumberFormatInfo.CurrentInfo, out var maxBigInt)); - - var random = BigInteger.One; - while (random <= BigInteger.One || random >= maxBigInt) - { - random = BigInteger.Random(2048); - } - } - - [TestMethod] - public void TestClientExhcangeGenerationItem130() - { - var test = "1090748135619415929450294929359784500348155124953172211774101106966150168922785639028532473848836817769712164169076432969224698752674677662739994265785437233596157045970922338040698100507861033047312331823982435279475700199860971612732540528796554502867919746776983759391475987142521315878719577519148811830879919426939958487087540965716419167467499326156226529675209172277001377591248147563782880558861083327174154014975134893125116015776318890295960698011614157721282527539468816519319333337503114777192360412281721018955834377615480468479252748867320362385355596601795122806756217713579819870634321561907813255153703950795271232652404894983869492174481652303803498881366210508647263668376514131031102336837488999775744046733651827239395353540348414872854639719294694323450186884189822544540647226987292160693184734654941906936646576130260972193280317171696418971553954161446191759093719524951116705577362073481319296041201283516154269044389257727700289684119460283480452306204130024913879981135908026983868205969318167819680850998649694416907952712904962404937775789698917207356355227455066183815847669135530549755439819480321732925869069136146085326382334628745456398071603058051634209386708703306545903199608523824513729625136659128221100967735450519952404248198262813831097374261650380017277916975324134846574681307337017380830353680623216336949471306191686438249305686413380231046096450953594089375540285037292470929395114028305547452584962074309438151825437902976012891749355198678420603722034900311364893046495761404333938686140037848030916292543273684533640032637639100774502371542479302473698388692892420946478947733800387782741417786484770190108867879778991633218628640533982619322466154883011452291890252336487236086654396093853898628805813177559162076363154436494477507871294119841637867701722166609831201845484078070518041336869808398454625586921201308185638888082699408686536045192649569198110353659943111802300636106509865023943661829436426563007917282050894429388841748885398290707743052973605359277515749619730823773215894755121761467887865327707115573804264519206349215850195195364813387526811742474131549802130246506341207020335797706780705406945275438806265978516209706795702579244075380490231741030862614968783306207869687868108423639971983209077624758080499988275591392787267627182442892809646874228263172435642368588260139161962836121481966092745325488641054238839295138992979335446110090325230955276870524611359124918392740353154294858383359"; - _ = BigInteger.TryParse(test, NumberStyles.Number, NumberFormatInfo.CurrentInfo, out var prime); - - BigInteger group = 2; - var bitLength = prime.BitLength; - - BigInteger clientExchangeValue; - do - { - var randomValue = BigInteger.Random(bitLength); - - //clientExchangeValue = BigInteger.ModPow(group, randomValue, prime); - clientExchangeValue = (group ^ randomValue) % prime; - } - while (clientExchangeValue < 1 || clientExchangeValue > (prime - 1)); - } - - [TestMethod] - public void TestClientExhcangeGenerationGroup1() - { - var test = "00FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"; - _ = BigInteger.TryParse(test, NumberStyles.AllowHexSpecifier, NumberFormatInfo.CurrentInfo, out var prime); - - BigInteger group = 2; - var bitLength = prime.BitLength; - - BigInteger clientExchangeValue; - do - { - var randomValue = BigInteger.Random(bitLength); - - //clientExchangeValue = BigInteger.ModPow(group, randomValue, prime); - clientExchangeValue = (group ^ randomValue) % prime; - } - while (clientExchangeValue < 1 || clientExchangeValue > (prime - 1)); - } - - [TestMethod] - public void TestClientExhcangeGenerationGroup14() - { - var test = "00FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF"; - _ = BigInteger.TryParse(test, NumberStyles.AllowHexSpecifier, NumberFormatInfo.CurrentInfo, out var prime); - - BigInteger group = 2; - var bitLength = prime.BitLength; - - BigInteger clientExchangeValue; - do - { - var randomValue = BigInteger.Random(bitLength); - - //clientExchangeValue = BigInteger.ModPow(group, randomValue, prime); - clientExchangeValue = (group ^ randomValue) % prime; - } - while (clientExchangeValue < 1 || clientExchangeValue > (prime - 1)); - } - - private static void AssertEqual(byte[] a, byte[] b) - { - Assert.IsTrue(a.IsEqualTo(b)); - } - } -} diff --git a/test/Renci.SshNet.Tests/Classes/Messages/Transport/KeyExchangeDhGroupExchangeGroupBuilder.cs b/test/Renci.SshNet.Tests/Classes/Messages/Transport/KeyExchangeDhGroupExchangeGroupBuilder.cs deleted file mode 100644 index c2dfe026b..000000000 --- a/test/Renci.SshNet.Tests/Classes/Messages/Transport/KeyExchangeDhGroupExchangeGroupBuilder.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Renci.SshNet.Common; -using Renci.SshNet.Messages.Transport; - -namespace Renci.SshNet.Tests.Classes.Messages.Transport -{ - public class KeyExchangeDhGroupExchangeGroupBuilder - { - private BigInteger _safePrime; - private BigInteger _subGroup; - - public KeyExchangeDhGroupExchangeGroupBuilder WithSafePrime(BigInteger safePrime) - { - _safePrime = safePrime; - return this; - } - - public KeyExchangeDhGroupExchangeGroupBuilder WithSubGroup(BigInteger subGroup) - { - _subGroup = subGroup; - return this; - } - - public byte[] Build() - { - var sshDataStream = new SshDataStream(0); - var target = new KeyExchangeDhGroupExchangeGroup(); - sshDataStream.WriteByte(target.MessageNumber); - sshDataStream.Write(_safePrime); - sshDataStream.Write(_subGroup); - return sshDataStream.ToArray(); - } - } -} diff --git a/test/Renci.SshNet.Tests/Classes/Messages/Transport/KeyExchangeDhGroupExchangeInitTest.cs b/test/Renci.SshNet.Tests/Classes/Messages/Transport/KeyExchangeDhGroupExchangeInitTest.cs deleted file mode 100644 index 0ffc4ba0d..000000000 --- a/test/Renci.SshNet.Tests/Classes/Messages/Transport/KeyExchangeDhGroupExchangeInitTest.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; - -using Renci.SshNet.Tests.Common; - -namespace Renci.SshNet.Tests.Classes.Messages.Transport -{ - /// - /// Represents SSH_MSG_KEX_DH_GEX_INIT message. - /// - [TestClass] - public class KeyExchangeDhGroupExchangeInitTest : TestBase - { - } -} diff --git a/test/Renci.SshNet.Tests/Classes/Messages/Transport/KeyExchangeDhGroupExchangeReplyBuilder.cs b/test/Renci.SshNet.Tests/Classes/Messages/Transport/KeyExchangeDhGroupExchangeReplyBuilder.cs deleted file mode 100644 index f36106f2b..000000000 --- a/test/Renci.SshNet.Tests/Classes/Messages/Transport/KeyExchangeDhGroupExchangeReplyBuilder.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Text; - -using Renci.SshNet.Common; -using Renci.SshNet.Messages.Transport; - -namespace Renci.SshNet.Tests.Classes.Messages.Transport -{ - public class KeyExchangeDhGroupExchangeReplyBuilder - { - private byte[] _hostKeyAlgorithm; - private byte[] _hostKeys; - private BigInteger _f; - private byte[] _signature; - - public KeyExchangeDhGroupExchangeReplyBuilder WithHostKey(string hostKeyAlgorithm, params BigInteger[] hostKeys) - { - _hostKeyAlgorithm = Encoding.UTF8.GetBytes(hostKeyAlgorithm); - - var sshDataStream = new SshDataStream(0); - foreach (var hostKey in hostKeys) - { - sshDataStream.Write(hostKey); - } - - _hostKeys = sshDataStream.ToArray(); - - return this; - } - - public KeyExchangeDhGroupExchangeReplyBuilder WithF(BigInteger f) - { - _f = f; - return this; - } - - public KeyExchangeDhGroupExchangeReplyBuilder WithSignature(byte[] signature) - { - _signature = signature; - return this; - } - - public byte[] Build() - { - var sshDataStream = new SshDataStream(0); - var target = new KeyExchangeDhGroupExchangeReply(); - sshDataStream.WriteByte(target.MessageNumber); - sshDataStream.Write((uint)(4 + _hostKeyAlgorithm.Length + _hostKeys.Length)); - sshDataStream.Write((uint)_hostKeyAlgorithm.Length); - sshDataStream.Write(_hostKeyAlgorithm, 0, _hostKeyAlgorithm.Length); - sshDataStream.Write(_hostKeys, 0, _hostKeys.Length); - sshDataStream.Write(_f); - sshDataStream.WriteBinary(_signature); - return sshDataStream.ToArray(); - } - } -} diff --git a/test/Renci.SshNet.Tests/Classes/Security/Cryptography/DsaDigitalSignatureTest.cs b/test/Renci.SshNet.Tests/Classes/Security/Cryptography/DsaDigitalSignatureTest.cs index 87b2e435f..695ec7ab4 100644 --- a/test/Renci.SshNet.Tests/Classes/Security/Cryptography/DsaDigitalSignatureTest.cs +++ b/test/Renci.SshNet.Tests/Classes/Security/Cryptography/DsaDigitalSignatureTest.cs @@ -3,6 +3,9 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Renci.SshNet.Abstractions; +#if !NET6_0_OR_GREATER +using Renci.SshNet.Common; +#endif using Renci.SshNet.Security; using Renci.SshNet.Security.Cryptography; using Renci.SshNet.Tests.Common; @@ -19,8 +22,8 @@ public void Verify() DsaKey dsaKey = GetDsaKey("Key.DSA.txt"); - Assert.AreEqual(1024, dsaKey.P.BitLength); - Assert.AreEqual(160, dsaKey.Q.BitLength); + Assert.AreEqual(1024, dsaKey.P.GetBitLength()); + Assert.AreEqual(160, dsaKey.Q.GetBitLength()); var digitalSignature = new DsaDigitalSignature(dsaKey); diff --git a/test/Renci.SshNet.Tests/Classes/Security/Cryptography/DsaKeyTest.cs b/test/Renci.SshNet.Tests/Classes/Security/Cryptography/DsaKeyTest.cs index aefc8e513..4f08eae07 100644 --- a/test/Renci.SshNet.Tests/Classes/Security/Cryptography/DsaKeyTest.cs +++ b/test/Renci.SshNet.Tests/Classes/Security/Cryptography/DsaKeyTest.cs @@ -5,6 +5,9 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +#if !NET6_0_OR_GREATER +using Renci.SshNet.Common; +#endif using Renci.SshNet.Security; using Renci.SshNet.Tests.Common; @@ -100,8 +103,8 @@ public void Key_DSA() { DsaKey dsaKey = GetDsaKey("Key.DSA.txt"); - Assert.AreEqual(1024, dsaKey.P.BitLength); - Assert.AreEqual(160, dsaKey.Q.BitLength); + Assert.AreEqual(1024, dsaKey.P.GetBitLength()); + Assert.AreEqual(160, dsaKey.Q.GetBitLength()); DSAParameters p = dsaKey.GetDSAParameters(); @@ -118,8 +121,8 @@ public void Key_SSH2_DSA_Encrypted_Des_CBC_12345() { DsaKey dsaKey = GetDsaKey("Key.SSH2.DSA.Encrypted.Des.CBC.12345.txt", "12345"); - Assert.AreEqual(1024, dsaKey.P.BitLength); - Assert.AreEqual(160, dsaKey.Q.BitLength); + Assert.AreEqual(1024, dsaKey.P.GetBitLength()); + Assert.AreEqual(160, dsaKey.Q.GetBitLength()); DSAParameters p = dsaKey.GetDSAParameters(); @@ -135,8 +138,8 @@ public void Key_SSH2_DSA() { DsaKey dsaKey = GetDsaKey("Key.SSH2.DSA.txt"); - Assert.AreEqual(1024, dsaKey.P.BitLength); - Assert.AreEqual(160, dsaKey.Q.BitLength); + Assert.AreEqual(1024, dsaKey.P.GetBitLength()); + Assert.AreEqual(160, dsaKey.Q.GetBitLength()); DSAParameters p = dsaKey.GetDSAParameters(); @@ -187,8 +190,8 @@ public void Key_DSA_3072_256() DsaKey dsaKey = (DsaKey)new PrivateKeyFile(stream).Key; - Assert.AreEqual(3072, dsaKey.P.BitLength); - Assert.AreEqual(256, dsaKey.Q.BitLength); + Assert.AreEqual(3072, dsaKey.P.GetBitLength()); + Assert.AreEqual(256, dsaKey.Q.GetBitLength()); DSAParameters p = dsaKey.GetDSAParameters();