BigIntegers.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math.Raw;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
  7. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities
  8. {
  9. /**
  10. * BigInteger utilities.
  11. */
  12. public static class BigIntegers
  13. {
  14. public static readonly BigInteger Zero = BigInteger.Zero;
  15. public static readonly BigInteger One = BigInteger.One;
  16. private const int MaxIterations = 1000;
  17. /**
  18. * Return the passed in value as an unsigned byte array.
  19. *
  20. * @param value the value to be converted.
  21. * @return a byte array without a leading zero byte if present in the signed encoding.
  22. */
  23. public static byte[] AsUnsignedByteArray(BigInteger n)
  24. {
  25. return n.ToByteArrayUnsigned();
  26. }
  27. /**
  28. * Return the passed in value as an unsigned byte array of the specified length, padded with
  29. * leading zeros as necessary.
  30. * @param length the fixed length of the result.
  31. * @param n the value to be converted.
  32. * @return a byte array padded to a fixed length with leading zeros.
  33. */
  34. public static byte[] AsUnsignedByteArray(int length, BigInteger n)
  35. {
  36. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  37. int bytesLength = n.GetLengthofByteArrayUnsigned();
  38. if (bytesLength > length)
  39. throw new ArgumentException("standard length exceeded", nameof(n));
  40. byte[] bytes = new byte[length];
  41. n.ToByteArrayUnsigned(bytes.AsSpan(length - bytesLength));
  42. return bytes;
  43. #else
  44. byte[] bytes = n.ToByteArrayUnsigned();
  45. int bytesLength = bytes.Length;
  46. if (bytesLength == length)
  47. return bytes;
  48. if (bytesLength > length)
  49. throw new ArgumentException("standard length exceeded", nameof(n));
  50. byte[] tmp = new byte[length];
  51. Array.Copy(bytes, 0, tmp, length - bytesLength, bytesLength);
  52. return tmp;
  53. #endif
  54. }
  55. /**
  56. * Write the passed in value as unsigned bytes to the specified buffer range, padded with
  57. * leading zeros as necessary.
  58. *
  59. * @param n
  60. * the value to be converted.
  61. * @param buf
  62. * the buffer to which the value is written.
  63. * @param off
  64. * the start offset in array <code>buf</code> at which the data is written.
  65. * @param len
  66. * the fixed length of data written (possibly padded with leading zeros).
  67. */
  68. public static void AsUnsignedByteArray(BigInteger n, byte[] buf, int off, int len)
  69. {
  70. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  71. AsUnsignedByteArray(n, buf.AsSpan(off, len));
  72. #else
  73. byte[] bytes = n.ToByteArrayUnsigned();
  74. int bytesLength = bytes.Length;
  75. if (bytesLength > len)
  76. throw new ArgumentException("standard length exceeded", nameof(n));
  77. int padLen = len - bytesLength;
  78. Arrays.Fill(buf, off, off + padLen, 0);
  79. Array.Copy(bytes, 0, buf, off + padLen, bytesLength);
  80. #endif
  81. }
  82. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  83. public static void AsUnsignedByteArray(BigInteger n, Span<byte> buf)
  84. {
  85. int bytesLength = n.GetLengthofByteArrayUnsigned();
  86. if (bytesLength > buf.Length)
  87. throw new ArgumentException("standard length exceeded", nameof(n));
  88. buf[..^bytesLength].Fill(0x00);
  89. n.ToByteArrayUnsigned(buf[^bytesLength..]);
  90. }
  91. #endif
  92. /// <summary>
  93. /// Creates a Random BigInteger from the secure random of a given bit length.
  94. /// </summary>
  95. /// <param name="bitLength"></param>
  96. /// <param name="secureRandom"></param>
  97. /// <returns></returns>
  98. public static BigInteger CreateRandomBigInteger(int bitLength, SecureRandom secureRandom)
  99. {
  100. return new BigInteger(bitLength, secureRandom);
  101. }
  102. /**
  103. * Return a random BigInteger not less than 'min' and not greater than 'max'
  104. *
  105. * @param min the least value that may be generated
  106. * @param max the greatest value that may be generated
  107. * @param random the source of randomness
  108. * @return a random BigInteger value in the range [min,max]
  109. */
  110. public static BigInteger CreateRandomInRange(
  111. BigInteger min,
  112. BigInteger max,
  113. // TODO Should have been just Random class
  114. SecureRandom random)
  115. {
  116. int cmp = min.CompareTo(max);
  117. if (cmp >= 0)
  118. {
  119. if (cmp > 0)
  120. throw new ArgumentException("'min' may not be greater than 'max'");
  121. return min;
  122. }
  123. if (min.BitLength > max.BitLength / 2)
  124. {
  125. return CreateRandomInRange(BigInteger.Zero, max.Subtract(min), random).Add(min);
  126. }
  127. for (int i = 0; i < MaxIterations; ++i)
  128. {
  129. BigInteger x = new BigInteger(max.BitLength, random);
  130. if (x.CompareTo(min) >= 0 && x.CompareTo(max) <= 0)
  131. {
  132. return x;
  133. }
  134. }
  135. // fall back to a faster (restricted) method
  136. return new BigInteger(max.Subtract(min).BitLength - 1, random).Add(min);
  137. }
  138. public static BigInteger ModOddInverse(BigInteger M, BigInteger X)
  139. {
  140. if (!M.TestBit(0))
  141. throw new ArgumentException("must be odd", "M");
  142. if (M.SignValue != 1)
  143. throw new ArithmeticException("BigInteger: modulus not positive");
  144. if (X.SignValue < 0 || X.CompareTo(M) >= 0)
  145. {
  146. X = X.Mod(M);
  147. }
  148. int bits = M.BitLength;
  149. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  150. if (bits <= 2048)
  151. {
  152. int len = Nat.GetLengthForBits(bits);
  153. Span<uint> m = stackalloc uint[len];
  154. Span<uint> x = stackalloc uint[len];
  155. Span<uint> z = stackalloc uint[len];
  156. Nat.FromBigInteger(bits, M, m);
  157. Nat.FromBigInteger(bits, X, x);
  158. if (0 == Mod.ModOddInverse(m, x, z))
  159. throw new ArithmeticException("BigInteger not invertible");
  160. return Nat.ToBigInteger(len, z);
  161. }
  162. else
  163. #endif
  164. {
  165. uint[] m = Nat.FromBigInteger(bits, M);
  166. uint[] x = Nat.FromBigInteger(bits, X);
  167. int len = m.Length;
  168. uint[] z = Nat.Create(len);
  169. if (0 == Mod.ModOddInverse(m, x, z))
  170. throw new ArithmeticException("BigInteger not invertible");
  171. return Nat.ToBigInteger(len, z);
  172. }
  173. }
  174. public static BigInteger ModOddInverseVar(BigInteger M, BigInteger X)
  175. {
  176. if (!M.TestBit(0))
  177. throw new ArgumentException("must be odd", "M");
  178. if (M.SignValue != 1)
  179. throw new ArithmeticException("BigInteger: modulus not positive");
  180. if (M.Equals(One))
  181. return Zero;
  182. if (X.SignValue < 0 || X.CompareTo(M) >= 0)
  183. {
  184. X = X.Mod(M);
  185. }
  186. if (X.Equals(One))
  187. return One;
  188. int bits = M.BitLength;
  189. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  190. if (bits <= 2048)
  191. {
  192. int len = Nat.GetLengthForBits(bits);
  193. Span<uint> m = stackalloc uint[len];
  194. Span<uint> x = stackalloc uint[len];
  195. Span<uint> z = stackalloc uint[len];
  196. Nat.FromBigInteger(bits, M, m);
  197. Nat.FromBigInteger(bits, X, x);
  198. if (!Mod.ModOddInverseVar(m, x, z))
  199. throw new ArithmeticException("BigInteger not invertible");
  200. return Nat.ToBigInteger(len, z);
  201. }
  202. else
  203. #endif
  204. {
  205. uint[] m = Nat.FromBigInteger(bits, M);
  206. uint[] x = Nat.FromBigInteger(bits, X);
  207. int len = m.Length;
  208. uint[] z = Nat.Create(len);
  209. if (!Mod.ModOddInverseVar(m, x, z))
  210. throw new ArithmeticException("BigInteger not invertible");
  211. return Nat.ToBigInteger(len, z);
  212. }
  213. }
  214. public static int GetByteLength(BigInteger n)
  215. {
  216. return n.GetLengthofByteArray();
  217. }
  218. public static int GetUnsignedByteLength(BigInteger n)
  219. {
  220. return n.GetLengthofByteArrayUnsigned();
  221. }
  222. }
  223. }
  224. #pragma warning restore
  225. #endif