SecT571Field.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Diagnostics;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math.Raw;
  6. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Math.EC.Custom.Sec
  7. {
  8. internal class SecT571Field
  9. {
  10. private const ulong M59 = ulong.MaxValue >> 5;
  11. private const ulong RM = 0xEF7BDEF7BDEF7BDEUL;
  12. private static readonly ulong[] ROOT_Z = new ulong[]{ 0x2BE1195F08CAFB99UL, 0x95F08CAF84657C23UL, 0xCAF84657C232BE11UL, 0x657C232BE1195F08UL,
  13. 0xF84657C2308CAF84UL, 0x7C232BE1195F08CAUL, 0xBE1195F08CAF8465UL, 0x5F08CAF84657C232UL, 0x784657C232BE119UL };
  14. public static void Add(ulong[] x, ulong[] y, ulong[] z)
  15. {
  16. for (int i = 0; i < 9; ++i)
  17. {
  18. z[i] = x[i] ^ y[i];
  19. }
  20. }
  21. private static void Add(ulong[] x, int xOff, ulong[] y, int yOff, ulong[] z, int zOff)
  22. {
  23. for (int i = 0; i < 9; ++i)
  24. {
  25. z[zOff + i] = x[xOff + i] ^ y[yOff + i];
  26. }
  27. }
  28. private static void AddBothTo(ulong[] x, int xOff, ulong[] y, int yOff, ulong[] z, int zOff)
  29. {
  30. for (int i = 0; i < 9; ++i)
  31. {
  32. z[zOff + i] ^= x[xOff + i] ^ y[yOff + i];
  33. }
  34. }
  35. public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz)
  36. {
  37. for (int i = 0; i < 18; ++i)
  38. {
  39. zz[i] = xx[i] ^ yy[i];
  40. }
  41. }
  42. public static void AddOne(ulong[] x, ulong[] z)
  43. {
  44. z[0] = x[0] ^ 1UL;
  45. for (int i = 1; i < 9; ++i)
  46. {
  47. z[i] = x[i];
  48. }
  49. }
  50. public static ulong[] FromBigInteger(BigInteger x)
  51. {
  52. ulong[] z = Nat576.FromBigInteger64(x);
  53. Reduce5(z, 0);
  54. return z;
  55. }
  56. public static void Invert(ulong[] x, ulong[] z)
  57. {
  58. if (Nat576.IsZero64(x))
  59. throw new InvalidOperationException();
  60. // Itoh-Tsujii inversion with bases { 2, 3, 5 }
  61. ulong[] t0 = Nat576.Create64();
  62. ulong[] t1 = Nat576.Create64();
  63. ulong[] t2 = Nat576.Create64();
  64. Square(x, t2);
  65. // 5 | 570
  66. Square(t2, t0);
  67. Square(t0, t1);
  68. Multiply(t0, t1, t0);
  69. SquareN(t0, 2, t1);
  70. Multiply(t0, t1, t0);
  71. Multiply(t0, t2, t0);
  72. // 3 | 114
  73. SquareN(t0, 5, t1);
  74. Multiply(t0, t1, t0);
  75. SquareN(t1, 5, t1);
  76. Multiply(t0, t1, t0);
  77. // 2 | 38
  78. SquareN(t0, 15, t1);
  79. Multiply(t0, t1, t2);
  80. // ! {2,3,5} | 19
  81. SquareN(t2, 30, t0);
  82. SquareN(t0, 30, t1);
  83. Multiply(t0, t1, t0);
  84. // 3 | 9
  85. SquareN(t0, 60, t1);
  86. Multiply(t0, t1, t0);
  87. SquareN(t1, 60, t1);
  88. Multiply(t0, t1, t0);
  89. // 3 | 3
  90. SquareN(t0, 180, t1);
  91. Multiply(t0, t1, t0);
  92. SquareN(t1, 180, t1);
  93. Multiply(t0, t1, t0);
  94. Multiply(t0, t2, z);
  95. }
  96. public static void Multiply(ulong[] x, ulong[] y, ulong[] z)
  97. {
  98. ulong[] tt = Nat576.CreateExt64();
  99. ImplMultiply(x, y, tt);
  100. Reduce(tt, z);
  101. }
  102. public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz)
  103. {
  104. ulong[] tt = Nat576.CreateExt64();
  105. ImplMultiply(x, y, tt);
  106. AddExt(zz, tt, zz);
  107. }
  108. public static void Reduce(ulong[] xx, ulong[] z)
  109. {
  110. ulong xx09 = xx[9];
  111. ulong u = xx[17], v = xx09;
  112. xx09 = v ^ (u >> 59) ^ (u >> 57) ^ (u >> 54) ^ (u >> 49);
  113. v = xx[8] ^ (u << 5) ^ (u << 7) ^ (u << 10) ^ (u << 15);
  114. for (int i = 16; i >= 10; --i)
  115. {
  116. u = xx[i];
  117. z[i - 8] = v ^ (u >> 59) ^ (u >> 57) ^ (u >> 54) ^ (u >> 49);
  118. v = xx[i - 9] ^ (u << 5) ^ (u << 7) ^ (u << 10) ^ (u << 15);
  119. }
  120. u = xx09;
  121. z[1] = v ^ (u >> 59) ^ (u >> 57) ^ (u >> 54) ^ (u >> 49);
  122. v = xx[0] ^ (u << 5) ^ (u << 7) ^ (u << 10) ^ (u << 15);
  123. ulong x08 = z[8];
  124. ulong t = x08 >> 59;
  125. z[0] = v ^ t ^ (t << 2) ^ (t << 5) ^ (t << 10);
  126. z[8] = x08 & M59;
  127. }
  128. public static void Reduce5(ulong[] z, int zOff)
  129. {
  130. ulong z8 = z[zOff + 8], t = z8 >> 59;
  131. z[zOff ] ^= t ^ (t << 2) ^ (t << 5) ^ (t << 10);
  132. z[zOff + 8] = z8 & M59;
  133. }
  134. public static void Sqrt(ulong[] x, ulong[] z)
  135. {
  136. ulong[] evn = Nat576.Create64(), odd = Nat576.Create64();
  137. int pos = 0;
  138. for (int i = 0; i < 4; ++i)
  139. {
  140. ulong u0 = Interleave.Unshuffle(x[pos++]);
  141. ulong u1 = Interleave.Unshuffle(x[pos++]);
  142. evn[i] = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
  143. odd[i] = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
  144. }
  145. {
  146. ulong u0 = Interleave.Unshuffle(x[pos]);
  147. evn[4] = (u0 & 0x00000000FFFFFFFFUL);
  148. odd[4] = (u0 >> 32);
  149. }
  150. Multiply(odd, ROOT_Z, z);
  151. Add(z, evn, z);
  152. }
  153. public static void Square(ulong[] x, ulong[] z)
  154. {
  155. ulong[] tt = Nat576.CreateExt64();
  156. ImplSquare(x, tt);
  157. Reduce(tt, z);
  158. }
  159. public static void SquareAddToExt(ulong[] x, ulong[] zz)
  160. {
  161. ulong[] tt = Nat576.CreateExt64();
  162. ImplSquare(x, tt);
  163. AddExt(zz, tt, zz);
  164. }
  165. public static void SquareN(ulong[] x, int n, ulong[] z)
  166. {
  167. Debug.Assert(n > 0);
  168. ulong[] tt = Nat576.CreateExt64();
  169. ImplSquare(x, tt);
  170. Reduce(tt, z);
  171. while (--n > 0)
  172. {
  173. ImplSquare(z, tt);
  174. Reduce(tt, z);
  175. }
  176. }
  177. public static uint Trace(ulong[] x)
  178. {
  179. // Non-zero-trace bits: 0, 561, 569
  180. return (uint)(x[0] ^ (x[8] >> 49) ^ (x[8] >> 57)) & 1U;
  181. }
  182. protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz)
  183. {
  184. //for (int i = 0; i < 9; ++i)
  185. //{
  186. // ImplMulwAcc(x, y[i], zz, i);
  187. //}
  188. /*
  189. * Precompute table of all 4-bit products of y
  190. */
  191. ulong[] T0 = new ulong[9 << 4];
  192. Array.Copy(y, 0, T0, 9, 9);
  193. // Reduce5(T0, 9);
  194. int tOff = 0;
  195. for (int i = 7; i > 0; --i)
  196. {
  197. tOff += 18;
  198. Nat.ShiftUpBit64(9, T0, tOff >> 1, 0UL, T0, tOff);
  199. Reduce5(T0, tOff);
  200. Add(T0, 9, T0, tOff, T0, tOff + 9);
  201. }
  202. /*
  203. * Second table with all 4-bit products of B shifted 4 bits
  204. */
  205. ulong[] T1 = new ulong[T0.Length];
  206. Nat.ShiftUpBits64(T0.Length, T0, 0, 4, 0L, T1, 0);
  207. uint MASK = 0xF;
  208. /*
  209. * Lopez-Dahab algorithm
  210. */
  211. for (int k = 56; k >= 0; k -= 8)
  212. {
  213. for (int j = 1; j < 9; j += 2)
  214. {
  215. uint aVal = (uint)(x[j] >> k);
  216. uint u = aVal & MASK;
  217. uint v = (aVal >> 4) & MASK;
  218. AddBothTo(T0, (int)(9 * u), T1, (int)(9 * v), zz, j - 1);
  219. }
  220. Nat.ShiftUpBits64(16, zz, 0, 8, 0L);
  221. }
  222. for (int k = 56; k >= 0; k -= 8)
  223. {
  224. for (int j = 0; j < 9; j += 2)
  225. {
  226. uint aVal = (uint)(x[j] >> k);
  227. uint u = aVal & MASK;
  228. uint v = (aVal >> 4) & MASK;
  229. AddBothTo(T0, (int)(9 * u), T1, (int)(9 * v), zz, j);
  230. }
  231. if (k > 0)
  232. {
  233. Nat.ShiftUpBits64(18, zz, 0, 8, 0L);
  234. }
  235. }
  236. }
  237. protected static void ImplMulwAcc(ulong[] xs, ulong y, ulong[] z, int zOff)
  238. {
  239. ulong[] u = new ulong[32];
  240. //u[0] = 0;
  241. u[1] = y;
  242. for (int i = 2; i < 32; i += 2)
  243. {
  244. u[i ] = u[i >> 1] << 1;
  245. u[i + 1] = u[i ] ^ y;
  246. }
  247. ulong l = 0;
  248. for (int i = 0; i < 9; ++i)
  249. {
  250. ulong x = xs[i];
  251. uint j = (uint)x;
  252. l ^= u[j & 31];
  253. ulong g, h = 0;
  254. int k = 60;
  255. do
  256. {
  257. j = (uint)(x >> k);
  258. g = u[j & 31];
  259. l ^= (g << k);
  260. h ^= (g >> -k);
  261. }
  262. while ((k -= 5) > 0);
  263. for (int p = 0; p < 4; ++p)
  264. {
  265. x = (x & RM) >> 1;
  266. h ^= x & (ulong)(((long)y << p) >> 63);
  267. }
  268. z[zOff + i] ^= l;
  269. l = h;
  270. }
  271. z[zOff + 9] ^= l;
  272. }
  273. protected static void ImplSquare(ulong[] x, ulong[] zz)
  274. {
  275. for (int i = 0; i < 9; ++i)
  276. {
  277. Interleave.Expand64To128(x[i], zz, i << 1);
  278. }
  279. }
  280. }
  281. }
  282. #pragma warning restore
  283. #endif