Mod.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using System.Diagnostics;
  4. using Org.BouncyCastle.Crypto.Utilities;
  5. using Org.BouncyCastle.Security;
  6. using Org.BouncyCastle.Utilities;
  7. namespace Org.BouncyCastle.Math.Raw
  8. {
  9. internal abstract class Mod
  10. {
  11. private static readonly SecureRandom RandomSource = new SecureRandom();
  12. public static void Invert(uint[] p, uint[] x, uint[] z)
  13. {
  14. int len = p.Length;
  15. if (Nat.IsZero(len, x))
  16. throw new ArgumentException("cannot be 0", "x");
  17. if (Nat.IsOne(len, x))
  18. {
  19. Array.Copy(x, 0, z, 0, len);
  20. return;
  21. }
  22. uint[] u = Nat.Copy(len, x);
  23. uint[] a = Nat.Create(len);
  24. a[0] = 1;
  25. int ac = 0;
  26. if ((u[0] & 1) == 0)
  27. {
  28. InversionStep(p, u, len, a, ref ac);
  29. }
  30. if (Nat.IsOne(len, u))
  31. {
  32. InversionResult(p, ac, a, z);
  33. return;
  34. }
  35. uint[] v = Nat.Copy(len, p);
  36. uint[] b = Nat.Create(len);
  37. int bc = 0;
  38. int uvLen = len;
  39. for (;;)
  40. {
  41. while (u[uvLen - 1] == 0 && v[uvLen - 1] == 0)
  42. {
  43. --uvLen;
  44. }
  45. if (Nat.Gte(len, u, v))
  46. {
  47. Nat.SubFrom(len, v, u);
  48. Debug.Assert((u[0] & 1) == 0);
  49. ac += Nat.SubFrom(len, b, a) - bc;
  50. InversionStep(p, u, uvLen, a, ref ac);
  51. if (Nat.IsOne(len, u))
  52. {
  53. InversionResult(p, ac, a, z);
  54. return;
  55. }
  56. }
  57. else
  58. {
  59. Nat.SubFrom(len, u, v);
  60. Debug.Assert((v[0] & 1) == 0);
  61. bc += Nat.SubFrom(len, a, b) - ac;
  62. InversionStep(p, v, uvLen, b, ref bc);
  63. if (Nat.IsOne(len, v))
  64. {
  65. InversionResult(p, bc, b, z);
  66. return;
  67. }
  68. }
  69. }
  70. }
  71. public static uint[] Random(uint[] p)
  72. {
  73. int len = p.Length;
  74. uint[] s = Nat.Create(len);
  75. uint m = p[len - 1];
  76. m |= m >> 1;
  77. m |= m >> 2;
  78. m |= m >> 4;
  79. m |= m >> 8;
  80. m |= m >> 16;
  81. do
  82. {
  83. byte[] bytes = new byte[len << 2];
  84. RandomSource.NextBytes(bytes);
  85. Pack.BE_To_UInt32(bytes, 0, s);
  86. s[len - 1] &= m;
  87. }
  88. while (Nat.Gte(len, s, p));
  89. return s;
  90. }
  91. public static void Add(uint[] p, uint[] x, uint[] y, uint[] z)
  92. {
  93. int len = p.Length;
  94. uint c = Nat.Add(len, x, y, z);
  95. if (c != 0)
  96. {
  97. Nat.SubFrom(len, p, z);
  98. }
  99. }
  100. public static void Subtract(uint[] p, uint[] x, uint[] y, uint[] z)
  101. {
  102. int len = p.Length;
  103. int c = Nat.Sub(len, x, y, z);
  104. if (c != 0)
  105. {
  106. Nat.AddTo(len, p, z);
  107. }
  108. }
  109. private static void InversionResult(uint[] p, int ac, uint[] a, uint[] z)
  110. {
  111. if (ac < 0)
  112. {
  113. Nat.Add(p.Length, a, p, z);
  114. }
  115. else
  116. {
  117. Array.Copy(a, 0, z, 0, p.Length);
  118. }
  119. }
  120. private static void InversionStep(uint[] p, uint[] u, int uLen, uint[] x, ref int xc)
  121. {
  122. int len = p.Length;
  123. int count = 0;
  124. while (u[0] == 0)
  125. {
  126. Nat.ShiftDownWord(uLen, u, 0);
  127. count += 32;
  128. }
  129. {
  130. int zeroes = GetTrailingZeroes(u[0]);
  131. if (zeroes > 0)
  132. {
  133. Nat.ShiftDownBits(uLen, u, zeroes, 0);
  134. count += zeroes;
  135. }
  136. }
  137. for (int i = 0; i < count; ++i)
  138. {
  139. if ((x[0] & 1) != 0)
  140. {
  141. if (xc < 0)
  142. {
  143. xc += (int)Nat.AddTo(len, p, x);
  144. }
  145. else
  146. {
  147. xc += Nat.SubFrom(len, p, x);
  148. }
  149. }
  150. Debug.Assert(xc == 0 || xc == -1);
  151. Nat.ShiftDownBit(len, x, (uint)xc);
  152. }
  153. }
  154. private static int GetTrailingZeroes(uint x)
  155. {
  156. Debug.Assert(x != 0);
  157. int count = 0;
  158. while ((x & 1) == 0)
  159. {
  160. x >>= 1;
  161. ++count;
  162. }
  163. return count;
  164. }
  165. }
  166. }
  167. #endif