BigIntegers.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math.Raw;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  7. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities
  8. {
  9. /**
  10. * BigInteger utilities.
  11. */
  12. public abstract 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(
  24. BigInteger n)
  25. {
  26. return n.ToByteArrayUnsigned();
  27. }
  28. /**
  29. * Return the passed in value as an unsigned byte array of the specified length, padded with
  30. * leading zeros as necessary.
  31. * @param length the fixed length of the result.
  32. * @param n the value to be converted.
  33. * @return a byte array padded to a fixed length with leading zeros.
  34. */
  35. public static byte[] AsUnsignedByteArray(int length, BigInteger n)
  36. {
  37. byte[] bytes = n.ToByteArrayUnsigned();
  38. if (bytes.Length > length)
  39. throw new ArgumentException("standard length exceeded", "n");
  40. if (bytes.Length == length)
  41. return bytes;
  42. byte[] tmp = new byte[length];
  43. Array.Copy(bytes, 0, tmp, tmp.Length - bytes.Length, bytes.Length);
  44. return tmp;
  45. }
  46. /**
  47. * Write the passed in value as unsigned bytes to the specified buffer range, padded with
  48. * leading zeros as necessary.
  49. *
  50. * @param value
  51. * the value to be converted.
  52. * @param buf
  53. * the buffer to which the value is written.
  54. * @param off
  55. * the start offset in array <code>buf</code> at which the data is written.
  56. * @param len
  57. * the fixed length of data written (possibly padded with leading zeros).
  58. */
  59. public static void AsUnsignedByteArray(BigInteger value, byte[] buf, int off, int len)
  60. {
  61. byte[] bytes = value.ToByteArrayUnsigned();
  62. if (bytes.Length == len)
  63. {
  64. Array.Copy(bytes, 0, buf, off, len);
  65. return;
  66. }
  67. int start = bytes[0] == 0 ? 1 : 0;
  68. int count = bytes.Length - start;
  69. if (count > len)
  70. throw new ArgumentException("standard length exceeded for value");
  71. int padLen = len - count;
  72. Arrays.Fill(buf, off, off + padLen, 0);
  73. Array.Copy(bytes, start, buf, off + padLen, count);
  74. }
  75. /// <summary>
  76. /// Creates a Random BigInteger from the secure random of a given bit length.
  77. /// </summary>
  78. /// <param name="bitLength"></param>
  79. /// <param name="secureRandom"></param>
  80. /// <returns></returns>
  81. public static BigInteger CreateRandomBigInteger(int bitLength, SecureRandom secureRandom)
  82. {
  83. return new BigInteger(bitLength, secureRandom);
  84. }
  85. /**
  86. * Return a random BigInteger not less than 'min' and not greater than 'max'
  87. *
  88. * @param min the least value that may be generated
  89. * @param max the greatest value that may be generated
  90. * @param random the source of randomness
  91. * @return a random BigInteger value in the range [min,max]
  92. */
  93. public static BigInteger CreateRandomInRange(
  94. BigInteger min,
  95. BigInteger max,
  96. // TODO Should have been just Random class
  97. SecureRandom random)
  98. {
  99. int cmp = min.CompareTo(max);
  100. if (cmp >= 0)
  101. {
  102. if (cmp > 0)
  103. throw new ArgumentException("'min' may not be greater than 'max'");
  104. return min;
  105. }
  106. if (min.BitLength > max.BitLength / 2)
  107. {
  108. return CreateRandomInRange(BigInteger.Zero, max.Subtract(min), random).Add(min);
  109. }
  110. for (int i = 0; i < MaxIterations; ++i)
  111. {
  112. BigInteger x = new BigInteger(max.BitLength, random);
  113. if (x.CompareTo(min) >= 0 && x.CompareTo(max) <= 0)
  114. {
  115. return x;
  116. }
  117. }
  118. // fall back to a faster (restricted) method
  119. return new BigInteger(max.Subtract(min).BitLength - 1, random).Add(min);
  120. }
  121. public static BigInteger ModOddInverse(BigInteger M, BigInteger X)
  122. {
  123. if (!M.TestBit(0))
  124. throw new ArgumentException("must be odd", "M");
  125. if (M.SignValue != 1)
  126. throw new ArithmeticException("BigInteger: modulus not positive");
  127. if (X.SignValue < 0 || X.CompareTo(M) >= 0)
  128. {
  129. X = X.Mod(M);
  130. }
  131. int bits = M.BitLength;
  132. uint[] m = Nat.FromBigInteger(bits, M);
  133. uint[] x = Nat.FromBigInteger(bits, X);
  134. int len = m.Length;
  135. uint[] z = Nat.Create(len);
  136. if (0 == Mod.ModOddInverse(m, x, z))
  137. throw new ArithmeticException("BigInteger not invertible");
  138. return Nat.ToBigInteger(len, z);
  139. }
  140. public static BigInteger ModOddInverseVar(BigInteger M, BigInteger X)
  141. {
  142. if (!M.TestBit(0))
  143. throw new ArgumentException("must be odd", "M");
  144. if (M.SignValue != 1)
  145. throw new ArithmeticException("BigInteger: modulus not positive");
  146. if (M.Equals(One))
  147. return Zero;
  148. if (X.SignValue < 0 || X.CompareTo(M) >= 0)
  149. {
  150. X = X.Mod(M);
  151. }
  152. if (X.Equals(One))
  153. return One;
  154. int bits = M.BitLength;
  155. uint[] m = Nat.FromBigInteger(bits, M);
  156. uint[] x = Nat.FromBigInteger(bits, X);
  157. int len = m.Length;
  158. uint[] z = Nat.Create(len);
  159. if (!Mod.ModOddInverseVar(m, x, z))
  160. throw new ArithmeticException("BigInteger not invertible");
  161. return Nat.ToBigInteger(len, z);
  162. }
  163. public static int GetUnsignedByteLength(BigInteger n)
  164. {
  165. return (n.BitLength + 7) / 8;
  166. }
  167. }
  168. }
  169. #pragma warning restore
  170. #endif