SecT571Field.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  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 static readonly ulong[] ROOT_Z = new ulong[]{ 0x2BE1195F08CAFB99UL, 0x95F08CAF84657C23UL,
  12. 0xCAF84657C232BE11UL, 0x657C232BE1195F08UL, 0xF84657C2308CAF84UL, 0x7C232BE1195F08CAUL,
  13. 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. public static void AddBothTo(ulong[] x, ulong[] y, ulong[] z)
  29. {
  30. for (int i = 0; i < 9; ++i)
  31. {
  32. z[i] ^= x[i] ^ y[i];
  33. }
  34. }
  35. private static void AddBothTo(ulong[] x, int xOff, ulong[] y, int yOff, ulong[] z, int zOff)
  36. {
  37. for (int i = 0; i < 9; ++i)
  38. {
  39. z[zOff + i] ^= x[xOff + i] ^ y[yOff + i];
  40. }
  41. }
  42. public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz)
  43. {
  44. for (int i = 0; i < 18; ++i)
  45. {
  46. zz[i] = xx[i] ^ yy[i];
  47. }
  48. }
  49. public static void AddOne(ulong[] x, ulong[] z)
  50. {
  51. z[0] = x[0] ^ 1UL;
  52. for (int i = 1; i < 9; ++i)
  53. {
  54. z[i] = x[i];
  55. }
  56. }
  57. private static void AddTo(ulong[] x, ulong[] z)
  58. {
  59. for (int i = 0; i < 9; ++i)
  60. {
  61. z[i] ^= x[i];
  62. }
  63. }
  64. public static ulong[] FromBigInteger(BigInteger x)
  65. {
  66. return Nat.FromBigInteger64(571, x);
  67. }
  68. public static void HalfTrace(ulong[] x, ulong[] z)
  69. {
  70. ulong[] tt = Nat576.CreateExt64();
  71. Nat576.Copy64(x, z);
  72. for (int i = 1; i < 571; i += 2)
  73. {
  74. ImplSquare(z, tt);
  75. Reduce(tt, z);
  76. ImplSquare(z, tt);
  77. Reduce(tt, z);
  78. AddTo(x, z);
  79. }
  80. }
  81. public static void Invert(ulong[] x, ulong[] z)
  82. {
  83. if (Nat576.IsZero64(x))
  84. throw new InvalidOperationException();
  85. // Itoh-Tsujii inversion with bases { 2, 3, 5 }
  86. ulong[] t0 = Nat576.Create64();
  87. ulong[] t1 = Nat576.Create64();
  88. ulong[] t2 = Nat576.Create64();
  89. Square(x, t2);
  90. // 5 | 570
  91. Square(t2, t0);
  92. Square(t0, t1);
  93. Multiply(t0, t1, t0);
  94. SquareN(t0, 2, t1);
  95. Multiply(t0, t1, t0);
  96. Multiply(t0, t2, t0);
  97. // 3 | 114
  98. SquareN(t0, 5, t1);
  99. Multiply(t0, t1, t0);
  100. SquareN(t1, 5, t1);
  101. Multiply(t0, t1, t0);
  102. // 2 | 38
  103. SquareN(t0, 15, t1);
  104. Multiply(t0, t1, t2);
  105. // ! {2,3,5} | 19
  106. SquareN(t2, 30, t0);
  107. SquareN(t0, 30, t1);
  108. Multiply(t0, t1, t0);
  109. // 3 | 9
  110. SquareN(t0, 60, t1);
  111. Multiply(t0, t1, t0);
  112. SquareN(t1, 60, t1);
  113. Multiply(t0, t1, t0);
  114. // 3 | 3
  115. SquareN(t0, 180, t1);
  116. Multiply(t0, t1, t0);
  117. SquareN(t1, 180, t1);
  118. Multiply(t0, t1, t0);
  119. Multiply(t0, t2, z);
  120. }
  121. public static void Multiply(ulong[] x, ulong[] y, ulong[] z)
  122. {
  123. ulong[] tt = Nat576.CreateExt64();
  124. ImplMultiply(x, y, tt);
  125. Reduce(tt, z);
  126. }
  127. public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz)
  128. {
  129. ulong[] tt = Nat576.CreateExt64();
  130. ImplMultiply(x, y, tt);
  131. AddExt(zz, tt, zz);
  132. }
  133. public static void MultiplyPrecomp(ulong[] x, ulong[] precomp, ulong[] z)
  134. {
  135. ulong[] tt = Nat576.CreateExt64();
  136. ImplMultiplyPrecomp(x, precomp, tt);
  137. Reduce(tt, z);
  138. }
  139. public static void MultiplyPrecompAddToExt(ulong[] x, ulong[] precomp, ulong[] zz)
  140. {
  141. ulong[] tt = Nat576.CreateExt64();
  142. ImplMultiplyPrecomp(x, precomp, tt);
  143. AddExt(zz, tt, zz);
  144. }
  145. public static ulong[] PrecompMultiplicand(ulong[] x)
  146. {
  147. /*
  148. * Precompute table of all 4-bit products of x (first section)
  149. */
  150. int len = 9 << 4;
  151. ulong[] t = new ulong[len << 1];
  152. Array.Copy(x, 0, t, 9, 9);
  153. //Reduce5(t, 9);
  154. int tOff = 0;
  155. for (int i = 7; i > 0; --i)
  156. {
  157. tOff += 18;
  158. Nat.ShiftUpBit64(9, t, tOff >> 1, 0UL, t, tOff);
  159. Reduce5(t, tOff);
  160. Add(t, 9, t, tOff, t, tOff + 9);
  161. }
  162. /*
  163. * Second section with all 4-bit products of x shifted 4 bits
  164. */
  165. Nat.ShiftUpBits64(len, t, 0, 4, 0UL, t, len);
  166. return t;
  167. }
  168. public static void Reduce(ulong[] xx, ulong[] z)
  169. {
  170. ulong xx09 = xx[9];
  171. ulong u = xx[17], v = xx09;
  172. xx09 = v ^ (u >> 59) ^ (u >> 57) ^ (u >> 54) ^ (u >> 49);
  173. v = xx[8] ^ (u << 5) ^ (u << 7) ^ (u << 10) ^ (u << 15);
  174. for (int i = 16; i >= 10; --i)
  175. {
  176. u = xx[i];
  177. z[i - 8] = v ^ (u >> 59) ^ (u >> 57) ^ (u >> 54) ^ (u >> 49);
  178. v = xx[i - 9] ^ (u << 5) ^ (u << 7) ^ (u << 10) ^ (u << 15);
  179. }
  180. u = xx09;
  181. z[1] = v ^ (u >> 59) ^ (u >> 57) ^ (u >> 54) ^ (u >> 49);
  182. v = xx[0] ^ (u << 5) ^ (u << 7) ^ (u << 10) ^ (u << 15);
  183. ulong x08 = z[8];
  184. ulong t = x08 >> 59;
  185. z[0] = v ^ t ^ (t << 2) ^ (t << 5) ^ (t << 10);
  186. z[8] = x08 & M59;
  187. }
  188. public static void Reduce5(ulong[] z, int zOff)
  189. {
  190. ulong z8 = z[zOff + 8], t = z8 >> 59;
  191. z[zOff ] ^= t ^ (t << 2) ^ (t << 5) ^ (t << 10);
  192. z[zOff + 8] = z8 & M59;
  193. }
  194. public static void Sqrt(ulong[] x, ulong[] z)
  195. {
  196. ulong[] evn = Nat576.Create64(), odd = Nat576.Create64();
  197. int pos = 0;
  198. for (int i = 0; i < 4; ++i)
  199. {
  200. ulong u0 = Interleave.Unshuffle(x[pos++]);
  201. ulong u1 = Interleave.Unshuffle(x[pos++]);
  202. evn[i] = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
  203. odd[i] = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
  204. }
  205. {
  206. ulong u0 = Interleave.Unshuffle(x[pos]);
  207. evn[4] = (u0 & 0x00000000FFFFFFFFUL);
  208. odd[4] = (u0 >> 32);
  209. }
  210. Multiply(odd, ROOT_Z, z);
  211. Add(z, evn, z);
  212. }
  213. public static void Square(ulong[] x, ulong[] z)
  214. {
  215. ulong[] tt = Nat576.CreateExt64();
  216. ImplSquare(x, tt);
  217. Reduce(tt, z);
  218. }
  219. public static void SquareAddToExt(ulong[] x, ulong[] zz)
  220. {
  221. ulong[] tt = Nat576.CreateExt64();
  222. ImplSquare(x, tt);
  223. AddExt(zz, tt, zz);
  224. }
  225. public static void SquareN(ulong[] x, int n, ulong[] z)
  226. {
  227. Debug.Assert(n > 0);
  228. ulong[] tt = Nat576.CreateExt64();
  229. ImplSquare(x, tt);
  230. Reduce(tt, z);
  231. while (--n > 0)
  232. {
  233. ImplSquare(z, tt);
  234. Reduce(tt, z);
  235. }
  236. }
  237. public static uint Trace(ulong[] x)
  238. {
  239. // Non-zero-trace bits: 0, 561, 569
  240. return (uint)(x[0] ^ (x[8] >> 49) ^ (x[8] >> 57)) & 1U;
  241. }
  242. protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz)
  243. {
  244. //ulong[] precomp = PrecompMultiplicand(y);
  245. //ImplMultiplyPrecomp(x, precomp, zz);
  246. ulong[] u = new ulong[16];
  247. for (int i = 0; i < 9; ++i)
  248. {
  249. ImplMulwAcc(u, x[i], y[i], zz, i << 1);
  250. }
  251. ulong v0 = zz[0], v1 = zz[1];
  252. v0 ^= zz[ 2]; zz[1] = v0 ^ v1; v1 ^= zz[ 3];
  253. v0 ^= zz[ 4]; zz[2] = v0 ^ v1; v1 ^= zz[ 5];
  254. v0 ^= zz[ 6]; zz[3] = v0 ^ v1; v1 ^= zz[ 7];
  255. v0 ^= zz[ 8]; zz[4] = v0 ^ v1; v1 ^= zz[ 9];
  256. v0 ^= zz[10]; zz[5] = v0 ^ v1; v1 ^= zz[11];
  257. v0 ^= zz[12]; zz[6] = v0 ^ v1; v1 ^= zz[13];
  258. v0 ^= zz[14]; zz[7] = v0 ^ v1; v1 ^= zz[15];
  259. v0 ^= zz[16]; zz[8] = v0 ^ v1; v1 ^= zz[17];
  260. ulong w = v0 ^ v1;
  261. zz[ 9] = zz[0] ^ w;
  262. zz[10] = zz[1] ^ w;
  263. zz[11] = zz[2] ^ w;
  264. zz[12] = zz[3] ^ w;
  265. zz[13] = zz[4] ^ w;
  266. zz[14] = zz[5] ^ w;
  267. zz[15] = zz[6] ^ w;
  268. zz[16] = zz[7] ^ w;
  269. zz[17] = zz[8] ^ w;
  270. ImplMulwAcc(u, x[0] ^ x[1], y[0] ^ y[1], zz, 1);
  271. ImplMulwAcc(u, x[0] ^ x[2], y[0] ^ y[2], zz, 2);
  272. ImplMulwAcc(u, x[0] ^ x[3], y[0] ^ y[3], zz, 3);
  273. ImplMulwAcc(u, x[1] ^ x[2], y[1] ^ y[2], zz, 3);
  274. ImplMulwAcc(u, x[0] ^ x[4], y[0] ^ y[4], zz, 4);
  275. ImplMulwAcc(u, x[1] ^ x[3], y[1] ^ y[3], zz, 4);
  276. ImplMulwAcc(u, x[0] ^ x[5], y[0] ^ y[5], zz, 5);
  277. ImplMulwAcc(u, x[1] ^ x[4], y[1] ^ y[4], zz, 5);
  278. ImplMulwAcc(u, x[2] ^ x[3], y[2] ^ y[3], zz, 5);
  279. ImplMulwAcc(u, x[0] ^ x[6], y[0] ^ y[6], zz, 6);
  280. ImplMulwAcc(u, x[1] ^ x[5], y[1] ^ y[5], zz, 6);
  281. ImplMulwAcc(u, x[2] ^ x[4], y[2] ^ y[4], zz, 6);
  282. ImplMulwAcc(u, x[0] ^ x[7], y[0] ^ y[7], zz, 7);
  283. ImplMulwAcc(u, x[1] ^ x[6], y[1] ^ y[6], zz, 7);
  284. ImplMulwAcc(u, x[2] ^ x[5], y[2] ^ y[5], zz, 7);
  285. ImplMulwAcc(u, x[3] ^ x[4], y[3] ^ y[4], zz, 7);
  286. ImplMulwAcc(u, x[0] ^ x[8], y[0] ^ y[8], zz, 8);
  287. ImplMulwAcc(u, x[1] ^ x[7], y[1] ^ y[7], zz, 8);
  288. ImplMulwAcc(u, x[2] ^ x[6], y[2] ^ y[6], zz, 8);
  289. ImplMulwAcc(u, x[3] ^ x[5], y[3] ^ y[5], zz, 8);
  290. ImplMulwAcc(u, x[1] ^ x[8], y[1] ^ y[8], zz, 9);
  291. ImplMulwAcc(u, x[2] ^ x[7], y[2] ^ y[7], zz, 9);
  292. ImplMulwAcc(u, x[3] ^ x[6], y[3] ^ y[6], zz, 9);
  293. ImplMulwAcc(u, x[4] ^ x[5], y[4] ^ y[5], zz, 9);
  294. ImplMulwAcc(u, x[2] ^ x[8], y[2] ^ y[8], zz, 10);
  295. ImplMulwAcc(u, x[3] ^ x[7], y[3] ^ y[7], zz, 10);
  296. ImplMulwAcc(u, x[4] ^ x[6], y[4] ^ y[6], zz, 10);
  297. ImplMulwAcc(u, x[3] ^ x[8], y[3] ^ y[8], zz, 11);
  298. ImplMulwAcc(u, x[4] ^ x[7], y[4] ^ y[7], zz, 11);
  299. ImplMulwAcc(u, x[5] ^ x[6], y[5] ^ y[6], zz, 11);
  300. ImplMulwAcc(u, x[4] ^ x[8], y[4] ^ y[8], zz, 12);
  301. ImplMulwAcc(u, x[5] ^ x[7], y[5] ^ y[7], zz, 12);
  302. ImplMulwAcc(u, x[5] ^ x[8], y[5] ^ y[8], zz, 13);
  303. ImplMulwAcc(u, x[6] ^ x[7], y[6] ^ y[7], zz, 13);
  304. ImplMulwAcc(u, x[6] ^ x[8], y[6] ^ y[8], zz, 14);
  305. ImplMulwAcc(u, x[7] ^ x[8], y[7] ^ y[8], zz, 15);
  306. }
  307. protected static void ImplMultiplyPrecomp(ulong[] x, ulong[] precomp, ulong[] zz)
  308. {
  309. uint MASK = 0xF;
  310. /*
  311. * Lopez-Dahab algorithm
  312. */
  313. for (int k = 56; k >= 0; k -= 8)
  314. {
  315. for (int j = 1; j < 9; j += 2)
  316. {
  317. uint aVal = (uint)(x[j] >> k);
  318. uint u = aVal & MASK;
  319. uint v = (aVal >> 4) & MASK;
  320. AddBothTo(precomp, (int)(9 * u), precomp, (int)(9 * (v + 16)), zz, j - 1);
  321. }
  322. Nat.ShiftUpBits64(16, zz, 0, 8, 0UL);
  323. }
  324. for (int k = 56; k >= 0; k -= 8)
  325. {
  326. for (int j = 0; j < 9; j += 2)
  327. {
  328. uint aVal = (uint)(x[j] >> k);
  329. uint u = aVal & MASK;
  330. uint v = (aVal >> 4) & MASK;
  331. AddBothTo(precomp, (int)(9 * u), precomp, (int)(9 * (v + 16)), zz, j);
  332. }
  333. if (k > 0)
  334. {
  335. Nat.ShiftUpBits64(18, zz, 0, 8, 0UL);
  336. }
  337. }
  338. }
  339. protected static void ImplMulwAcc(ulong[] u, ulong x, ulong y, ulong[] z, int zOff)
  340. {
  341. //u[0] = 0;
  342. u[1] = y;
  343. for (int i = 2; i < 16; i += 2)
  344. {
  345. u[i ] = u[i >> 1] << 1;
  346. u[i + 1] = u[i ] ^ y;
  347. }
  348. uint j = (uint)x;
  349. ulong g, h = 0, l = u[j & 15]
  350. ^ u[(j >> 4) & 15] << 4;
  351. int k = 56;
  352. do
  353. {
  354. j = (uint)(x >> k);
  355. g = u[j & 15]
  356. ^ u[(j >> 4) & 15] << 4;
  357. l ^= (g << k);
  358. h ^= (g >> -k);
  359. }
  360. while ((k -= 8) > 0);
  361. for (int p = 0; p < 7; ++p)
  362. {
  363. x = (x & 0xFEFEFEFEFEFEFEFEUL) >> 1;
  364. h ^= x & (ulong)((long)(y << p) >> 63);
  365. }
  366. Debug.Assert(h >> 63 == 0);
  367. z[zOff ] ^= l;
  368. z[zOff + 1] ^= h;
  369. }
  370. protected static void ImplSquare(ulong[] x, ulong[] zz)
  371. {
  372. Interleave.Expand64To128(x, 0, 9, zz, 0);
  373. }
  374. }
  375. }
  376. #pragma warning restore
  377. #endif