X448Field.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  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.Rfc7748
  7. {
  8. [CLSCompliantAttribute(false)]
  9. public abstract class X448Field
  10. {
  11. public const int Size = 16;
  12. private const uint M28 = 0x0FFFFFFFU;
  13. private X448Field() {}
  14. public static void Add(uint[] x, uint[] y, uint[] z)
  15. {
  16. for (int i = 0; i < Size; ++i)
  17. {
  18. z[i] = x[i] + y[i];
  19. }
  20. }
  21. public static void AddOne(uint[] z)
  22. {
  23. z[0] += 1;
  24. }
  25. public static void AddOne(uint[] z, int zOff)
  26. {
  27. z[zOff] += 1;
  28. }
  29. //public static void Apm(int[] x, int[] y, int[] zp, int[] zm)
  30. //{
  31. // for (int i = 0; i < Size; ++i)
  32. // {
  33. // int xi = x[i], yi = y[i];
  34. // zp[i] = xi + yi;
  35. // zm[i] = xi - yi;
  36. // }
  37. //}
  38. public static void Carry(uint[] z)
  39. {
  40. uint z0 = z[0], z1 = z[1], z2 = z[2], z3 = z[3], z4 = z[4], z5 = z[5], z6 = z[6], z7 = z[7];
  41. uint z8 = z[8], z9 = z[9], z10 = z[10], z11 = z[11], z12 = z[12], z13 = z[13], z14 = z[14], z15 = z[15];
  42. z2 += (z1 >> 28); z1 &= M28;
  43. z6 += (z5 >> 28); z5 &= M28;
  44. z10 += (z9 >> 28); z9 &= M28;
  45. z14 += (z13 >> 28); z13 &= M28;
  46. z3 += (z2 >> 28); z2 &= M28;
  47. z7 += (z6 >> 28); z6 &= M28;
  48. z11 += (z10 >> 28); z10 &= M28;
  49. z15 += (z14 >> 28); z14 &= M28;
  50. uint t = z15 >> 28; z15 &= M28;
  51. z0 += t;
  52. z8 += t;
  53. z4 += (z3 >> 28); z3 &= M28;
  54. z8 += (z7 >> 28); z7 &= M28;
  55. z12 += (z11 >> 28); z11 &= M28;
  56. z1 += (z0 >> 28); z0 &= M28;
  57. z5 += (z4 >> 28); z4 &= M28;
  58. z9 += (z8 >> 28); z8 &= M28;
  59. z13 += (z12 >> 28); z12 &= M28;
  60. z[0] = z0; z[1] = z1; z[2] = z2; z[3] = z3; z[4] = z4; z[5] = z5; z[6] = z6; z[7] = z7;
  61. z[8] = z8; z[9] = z9; z[10] = z10; z[11] = z11; z[12] = z12; z[13] = z13; z[14] = z14; z[15] = z15;
  62. }
  63. public static void CNegate(int negate, uint[] z)
  64. {
  65. Debug.Assert(negate >> 1 == 0);
  66. uint[] t = Create();
  67. Sub(t, z, t);
  68. Nat.CMov(Size, negate, t, 0, z, 0);
  69. }
  70. public static void Copy(uint[] x, int xOff, uint[] z, int zOff)
  71. {
  72. for (int i = 0; i < Size; ++i)
  73. {
  74. z[zOff + i] = x[xOff + i];
  75. }
  76. }
  77. public static uint[] Create()
  78. {
  79. return new uint[Size];
  80. }
  81. public static void CSwap(int swap, uint[] a, uint[] b)
  82. {
  83. Debug.Assert(swap >> 1 == 0);
  84. Debug.Assert(a != b);
  85. uint mask = (uint)(0 - swap);
  86. for (int i = 0; i < Size; ++i)
  87. {
  88. uint ai = a[i], bi = b[i];
  89. uint dummy = mask & (ai ^ bi);
  90. a[i] = ai ^ dummy;
  91. b[i] = bi ^ dummy;
  92. }
  93. }
  94. public static void Decode(byte[] x, int xOff, uint[] z)
  95. {
  96. Decode56(x, xOff, z, 0);
  97. Decode56(x, xOff + 7, z, 2);
  98. Decode56(x, xOff + 14, z, 4);
  99. Decode56(x, xOff + 21, z, 6);
  100. Decode56(x, xOff + 28, z, 8);
  101. Decode56(x, xOff + 35, z, 10);
  102. Decode56(x, xOff + 42, z, 12);
  103. Decode56(x, xOff + 49, z, 14);
  104. }
  105. private static uint Decode24(byte[] bs, int off)
  106. {
  107. uint n = bs[off];
  108. n |= (uint)bs[++off] << 8;
  109. n |= (uint)bs[++off] << 16;
  110. return n;
  111. }
  112. private static uint Decode32(byte[] bs, int off)
  113. {
  114. uint n = bs[off];
  115. n |= (uint)bs[++off] << 8;
  116. n |= (uint)bs[++off] << 16;
  117. n |= (uint)bs[++off] << 24;
  118. return n;
  119. }
  120. private static void Decode56(byte[] bs, int off, uint[] z, int zOff)
  121. {
  122. uint lo = Decode32(bs, off);
  123. uint hi = Decode24(bs, off + 4);
  124. z[zOff] = lo & M28;
  125. z[zOff + 1] = (lo >> 28) | (hi << 4);
  126. }
  127. public static void Encode(uint[] x, byte[] z, int zOff)
  128. {
  129. Encode56(x, 0, z, zOff);
  130. Encode56(x, 2, z, zOff + 7);
  131. Encode56(x, 4, z, zOff + 14);
  132. Encode56(x, 6, z, zOff + 21);
  133. Encode56(x, 8, z, zOff + 28);
  134. Encode56(x, 10, z, zOff + 35);
  135. Encode56(x, 12, z, zOff + 42);
  136. Encode56(x, 14, z, zOff + 49);
  137. }
  138. private static void Encode24(uint n, byte[] bs, int off)
  139. {
  140. bs[ off] = (byte)(n );
  141. bs[++off] = (byte)(n >> 8);
  142. bs[++off] = (byte)(n >> 16);
  143. }
  144. private static void Encode32(uint n, byte[] bs, int off)
  145. {
  146. bs[ off] = (byte)(n );
  147. bs[++off] = (byte)(n >> 8);
  148. bs[++off] = (byte)(n >> 16);
  149. bs[++off] = (byte)(n >> 24);
  150. }
  151. private static void Encode56(uint[] x, int xOff, byte[] bs, int off)
  152. {
  153. uint lo = x[xOff], hi = x[xOff + 1];
  154. Encode32(lo | (hi << 28), bs, off);
  155. Encode24(hi >> 4, bs, off + 4);
  156. }
  157. public static void Inv(uint[] x, uint[] z)
  158. {
  159. // z = x^(p-2) = x^(2^448 - 2^224 - 3)
  160. // (223 1s) (1 0s) (222 1s) (1 0s) (1 1s)
  161. // Addition chain: [1] 2 3 6 9 18 19 37 74 111 [222] [223]
  162. uint[] t = Create();
  163. PowPm3d4(x, t);
  164. Sqr(t, 2, t);
  165. Mul(t, x, z);
  166. }
  167. public static bool IsZeroVar(uint[] x)
  168. {
  169. uint d = 0;
  170. for (int i = 0; i < Size; ++i)
  171. {
  172. d |= x[i];
  173. }
  174. return d == 0U;
  175. }
  176. public static void Mul(uint[] x, uint y, uint[] z)
  177. {
  178. uint x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7];
  179. uint x8 = x[8], x9 = x[9], x10 = x[10], x11 = x[11], x12 = x[12], x13 = x[13], x14 = x[14], x15 = x[15];
  180. uint z1, z5, z9, z13;
  181. ulong c, d, e, f;
  182. c = (ulong)x1 * y;
  183. z1 = (uint)c & M28; c >>= 28;
  184. d = (ulong)x5 * y;
  185. z5 = (uint)d & M28; d >>= 28;
  186. e = (ulong)x9 * y;
  187. z9 = (uint)e & M28; e >>= 28;
  188. f = (ulong)x13 * y;
  189. z13 = (uint)f & M28; f >>= 28;
  190. c += (ulong)x2 * y;
  191. z[2] = (uint)c & M28; c >>= 28;
  192. d += (ulong)x6 * y;
  193. z[6] = (uint)d & M28; d >>= 28;
  194. e += (ulong)x10 * y;
  195. z[10] = (uint)e & M28; e >>= 28;
  196. f += (ulong)x14 * y;
  197. z[14] = (uint)f & M28; f >>= 28;
  198. c += (ulong)x3 * y;
  199. z[3] = (uint)c & M28; c >>= 28;
  200. d += (ulong)x7 * y;
  201. z[7] = (uint)d & M28; d >>= 28;
  202. e += (ulong)x11 * y;
  203. z[11] = (uint)e & M28; e >>= 28;
  204. f += (ulong)x15 * y;
  205. z[15] = (uint)f & M28; f >>= 28;
  206. d += f;
  207. c += (ulong)x4 * y;
  208. z[4] = (uint)c & M28; c >>= 28;
  209. d += (ulong)x8 * y;
  210. z[8] = (uint)d & M28; d >>= 28;
  211. e += (ulong)x12 * y;
  212. z[12] = (uint)e & M28; e >>= 28;
  213. f += (ulong)x0 * y;
  214. z[0] = (uint)f & M28; f >>= 28;
  215. z[1] = z1 + (uint)f;
  216. z[5] = z5 + (uint)c;
  217. z[9] = z9 + (uint)d;
  218. z[13] = z13 + (uint)e;
  219. }
  220. public static void Mul(uint[] x, uint[] y, uint[] z)
  221. {
  222. uint x0 = x[0];
  223. uint x1 = x[1];
  224. uint x2 = x[2];
  225. uint x3 = x[3];
  226. uint x4 = x[4];
  227. uint x5 = x[5];
  228. uint x6 = x[6];
  229. uint x7 = x[7];
  230. uint u0 = x[8];
  231. uint u1 = x[9];
  232. uint u2 = x[10];
  233. uint u3 = x[11];
  234. uint u4 = x[12];
  235. uint u5 = x[13];
  236. uint u6 = x[14];
  237. uint u7 = x[15];
  238. uint y0 = y[0];
  239. uint y1 = y[1];
  240. uint y2 = y[2];
  241. uint y3 = y[3];
  242. uint y4 = y[4];
  243. uint y5 = y[5];
  244. uint y6 = y[6];
  245. uint y7 = y[7];
  246. uint v0 = y[8];
  247. uint v1 = y[9];
  248. uint v2 = y[10];
  249. uint v3 = y[11];
  250. uint v4 = y[12];
  251. uint v5 = y[13];
  252. uint v6 = y[14];
  253. uint v7 = y[15];
  254. uint s0 = x0 + u0;
  255. uint s1 = x1 + u1;
  256. uint s2 = x2 + u2;
  257. uint s3 = x3 + u3;
  258. uint s4 = x4 + u4;
  259. uint s5 = x5 + u5;
  260. uint s6 = x6 + u6;
  261. uint s7 = x7 + u7;
  262. uint t0 = y0 + v0;
  263. uint t1 = y1 + v1;
  264. uint t2 = y2 + v2;
  265. uint t3 = y3 + v3;
  266. uint t4 = y4 + v4;
  267. uint t5 = y5 + v5;
  268. uint t6 = y6 + v6;
  269. uint t7 = y7 + v7;
  270. uint z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15;
  271. ulong c, d;
  272. ulong f0 = (ulong)x0 * y0;
  273. ulong f8 = (ulong)x7 * y1
  274. + (ulong)x6 * y2
  275. + (ulong)x5 * y3
  276. + (ulong)x4 * y4
  277. + (ulong)x3 * y5
  278. + (ulong)x2 * y6
  279. + (ulong)x1 * y7;
  280. ulong g0 = (ulong)u0 * v0;
  281. ulong g8 = (ulong)u7 * v1
  282. + (ulong)u6 * v2
  283. + (ulong)u5 * v3
  284. + (ulong)u4 * v4
  285. + (ulong)u3 * v5
  286. + (ulong)u2 * v6
  287. + (ulong)u1 * v7;
  288. ulong h0 = (ulong)s0 * t0;
  289. ulong h8 = (ulong)s7 * t1
  290. + (ulong)s6 * t2
  291. + (ulong)s5 * t3
  292. + (ulong)s4 * t4
  293. + (ulong)s3 * t5
  294. + (ulong)s2 * t6
  295. + (ulong)s1 * t7;
  296. c = f0 + g0 + h8 - f8;
  297. z0 = (uint)c & M28; c >>= 28;
  298. d = g8 + h0 - f0 + h8;
  299. z8 = (uint)d & M28; d >>= 28;
  300. ulong f1 = (ulong)x1 * y0
  301. + (ulong)x0 * y1;
  302. ulong f9 = (ulong)x7 * y2
  303. + (ulong)x6 * y3
  304. + (ulong)x5 * y4
  305. + (ulong)x4 * y5
  306. + (ulong)x3 * y6
  307. + (ulong)x2 * y7;
  308. ulong g1 = (ulong)u1 * v0
  309. + (ulong)u0 * v1;
  310. ulong g9 = (ulong)u7 * v2
  311. + (ulong)u6 * v3
  312. + (ulong)u5 * v4
  313. + (ulong)u4 * v5
  314. + (ulong)u3 * v6
  315. + (ulong)u2 * v7;
  316. ulong h1 = (ulong)s1 * t0
  317. + (ulong)s0 * t1;
  318. ulong h9 = (ulong)s7 * t2
  319. + (ulong)s6 * t3
  320. + (ulong)s5 * t4
  321. + (ulong)s4 * t5
  322. + (ulong)s3 * t6
  323. + (ulong)s2 * t7;
  324. c += f1 + g1 + h9 - f9;
  325. z1 = (uint)c & M28; c >>= 28;
  326. d += g9 + h1 - f1 + h9;
  327. z9 = (uint)d & M28; d >>= 28;
  328. ulong f2 = (ulong)x2 * y0
  329. + (ulong)x1 * y1
  330. + (ulong)x0 * y2;
  331. ulong f10 = (ulong)x7 * y3
  332. + (ulong)x6 * y4
  333. + (ulong)x5 * y5
  334. + (ulong)x4 * y6
  335. + (ulong)x3 * y7;
  336. ulong g2 = (ulong)u2 * v0
  337. + (ulong)u1 * v1
  338. + (ulong)u0 * v2;
  339. ulong g10 = (ulong)u7 * v3
  340. + (ulong)u6 * v4
  341. + (ulong)u5 * v5
  342. + (ulong)u4 * v6
  343. + (ulong)u3 * v7;
  344. ulong h2 = (ulong)s2 * t0
  345. + (ulong)s1 * t1
  346. + (ulong)s0 * t2;
  347. ulong h10 = (ulong)s7 * t3
  348. + (ulong)s6 * t4
  349. + (ulong)s5 * t5
  350. + (ulong)s4 * t6
  351. + (ulong)s3 * t7;
  352. c += f2 + g2 + h10 - f10;
  353. z2 = (uint)c & M28; c >>= 28;
  354. d += g10 + h2 - f2 + h10;
  355. z10 = (uint)d & M28; d >>= 28;
  356. ulong f3 = (ulong)x3 * y0
  357. + (ulong)x2 * y1
  358. + (ulong)x1 * y2
  359. + (ulong)x0 * y3;
  360. ulong f11 = (ulong)x7 * y4
  361. + (ulong)x6 * y5
  362. + (ulong)x5 * y6
  363. + (ulong)x4 * y7;
  364. ulong g3 = (ulong)u3 * v0
  365. + (ulong)u2 * v1
  366. + (ulong)u1 * v2
  367. + (ulong)u0 * v3;
  368. ulong g11 = (ulong)u7 * v4
  369. + (ulong)u6 * v5
  370. + (ulong)u5 * v6
  371. + (ulong)u4 * v7;
  372. ulong h3 = (ulong)s3 * t0
  373. + (ulong)s2 * t1
  374. + (ulong)s1 * t2
  375. + (ulong)s0 * t3;
  376. ulong h11 = (ulong)s7 * t4
  377. + (ulong)s6 * t5
  378. + (ulong)s5 * t6
  379. + (ulong)s4 * t7;
  380. c += f3 + g3 + h11 - f11;
  381. z3 = (uint)c & M28; c >>= 28;
  382. d += g11 + h3 - f3 + h11;
  383. z11 = (uint)d & M28; d >>= 28;
  384. ulong f4 = (ulong)x4 * y0
  385. + (ulong)x3 * y1
  386. + (ulong)x2 * y2
  387. + (ulong)x1 * y3
  388. + (ulong)x0 * y4;
  389. ulong f12 = (ulong)x7 * y5
  390. + (ulong)x6 * y6
  391. + (ulong)x5 * y7;
  392. ulong g4 = (ulong)u4 * v0
  393. + (ulong)u3 * v1
  394. + (ulong)u2 * v2
  395. + (ulong)u1 * v3
  396. + (ulong)u0 * v4;
  397. ulong g12 = (ulong)u7 * v5
  398. + (ulong)u6 * v6
  399. + (ulong)u5 * v7;
  400. ulong h4 = (ulong)s4 * t0
  401. + (ulong)s3 * t1
  402. + (ulong)s2 * t2
  403. + (ulong)s1 * t3
  404. + (ulong)s0 * t4;
  405. ulong h12 = (ulong)s7 * t5
  406. + (ulong)s6 * t6
  407. + (ulong)s5 * t7;
  408. c += f4 + g4 + h12 - f12;
  409. z4 = (uint)c & M28; c >>= 28;
  410. d += g12 + h4 - f4 + h12;
  411. z12 = (uint)d & M28; d >>= 28;
  412. ulong f5 = (ulong)x5 * y0
  413. + (ulong)x4 * y1
  414. + (ulong)x3 * y2
  415. + (ulong)x2 * y3
  416. + (ulong)x1 * y4
  417. + (ulong)x0 * y5;
  418. ulong f13 = (ulong)x7 * y6
  419. + (ulong)x6 * y7;
  420. ulong g5 = (ulong)u5 * v0
  421. + (ulong)u4 * v1
  422. + (ulong)u3 * v2
  423. + (ulong)u2 * v3
  424. + (ulong)u1 * v4
  425. + (ulong)u0 * v5;
  426. ulong g13 = (ulong)u7 * v6
  427. + (ulong)u6 * v7;
  428. ulong h5 = (ulong)s5 * t0
  429. + (ulong)s4 * t1
  430. + (ulong)s3 * t2
  431. + (ulong)s2 * t3
  432. + (ulong)s1 * t4
  433. + (ulong)s0 * t5;
  434. ulong h13 = (ulong)s7 * t6
  435. + (ulong)s6 * t7;
  436. c += f5 + g5 + h13 - f13;
  437. z5 = (uint)c & M28; c >>= 28;
  438. d += g13 + h5 - f5 + h13;
  439. z13 = (uint)d & M28; d >>= 28;
  440. ulong f6 = (ulong)x6 * y0
  441. + (ulong)x5 * y1
  442. + (ulong)x4 * y2
  443. + (ulong)x3 * y3
  444. + (ulong)x2 * y4
  445. + (ulong)x1 * y5
  446. + (ulong)x0 * y6;
  447. ulong f14 = (ulong)x7 * y7;
  448. ulong g6 = (ulong)u6 * v0
  449. + (ulong)u5 * v1
  450. + (ulong)u4 * v2
  451. + (ulong)u3 * v3
  452. + (ulong)u2 * v4
  453. + (ulong)u1 * v5
  454. + (ulong)u0 * v6;
  455. ulong g14 = (ulong)u7 * v7;
  456. ulong h6 = (ulong)s6 * t0
  457. + (ulong)s5 * t1
  458. + (ulong)s4 * t2
  459. + (ulong)s3 * t3
  460. + (ulong)s2 * t4
  461. + (ulong)s1 * t5
  462. + (ulong)s0 * t6;
  463. ulong h14 = (ulong)s7 * t7;
  464. c += f6 + g6 + h14 - f14;
  465. z6 = (uint)c & M28; c >>= 28;
  466. d += g14 + h6 - f6 + h14;
  467. z14 = (uint)d & M28; d >>= 28;
  468. ulong f7 = (ulong)x7 * y0
  469. + (ulong)x6 * y1
  470. + (ulong)x5 * y2
  471. + (ulong)x4 * y3
  472. + (ulong)x3 * y4
  473. + (ulong)x2 * y5
  474. + (ulong)x1 * y6
  475. + (ulong)x0 * y7;
  476. ulong g7 = (ulong)u7 * v0
  477. + (ulong)u6 * v1
  478. + (ulong)u5 * v2
  479. + (ulong)u4 * v3
  480. + (ulong)u3 * v4
  481. + (ulong)u2 * v5
  482. + (ulong)u1 * v6
  483. + (ulong)u0 * v7;
  484. ulong h7 = (ulong)s7 * t0
  485. + (ulong)s6 * t1
  486. + (ulong)s5 * t2
  487. + (ulong)s4 * t3
  488. + (ulong)s3 * t4
  489. + (ulong)s2 * t5
  490. + (ulong)s1 * t6
  491. + (ulong)s0 * t7;
  492. c += f7 + g7;
  493. z7 = (uint)c & M28; c >>= 28;
  494. d += h7 - f7;
  495. z15 = (uint)d & M28; d >>= 28;
  496. c += d;
  497. c += z8;
  498. z8 = (uint)c & M28; c >>= 28;
  499. d += z0;
  500. z0 = (uint)d & M28; d >>= 28;
  501. z9 += (uint)c;
  502. z1 += (uint)d;
  503. z[0] = z0;
  504. z[1] = z1;
  505. z[2] = z2;
  506. z[3] = z3;
  507. z[4] = z4;
  508. z[5] = z5;
  509. z[6] = z6;
  510. z[7] = z7;
  511. z[8] = z8;
  512. z[9] = z9;
  513. z[10] = z10;
  514. z[11] = z11;
  515. z[12] = z12;
  516. z[13] = z13;
  517. z[14] = z14;
  518. z[15] = z15;
  519. }
  520. public static void Negate(uint[] x, uint[] z)
  521. {
  522. uint[] zero = Create();
  523. Sub(zero, x, z);
  524. }
  525. public static void Normalize(uint[] z)
  526. {
  527. //int x = (z[15] >> (28 - 1)) & 1;
  528. Reduce(z, 1);
  529. Reduce(z, -1);
  530. Debug.Assert(z[15] >> 28 == 0U);
  531. }
  532. public static void One(uint[] z)
  533. {
  534. z[0] = 1U;
  535. for (int i = 1; i < Size; ++i)
  536. {
  537. z[i] = 0;
  538. }
  539. }
  540. private static void PowPm3d4(uint[] x, uint[] z)
  541. {
  542. // z = x^((p-3)/4) = x^(2^446 - 2^222 - 1)
  543. // (223 1s) (1 0s) (222 1s)
  544. // Addition chain: 1 2 3 6 9 18 19 37 74 111 [222] [223]
  545. uint[] x2 = Create(); Sqr(x, x2); Mul(x, x2, x2);
  546. uint[] x3 = Create(); Sqr(x2, x3); Mul(x, x3, x3);
  547. uint[] x6 = Create(); Sqr(x3, 3, x6); Mul(x3, x6, x6);
  548. uint[] x9 = Create(); Sqr(x6, 3, x9); Mul(x3, x9, x9);
  549. uint[] x18 = Create(); Sqr(x9, 9, x18); Mul(x9, x18, x18);
  550. uint[] x19 = Create(); Sqr(x18, x19); Mul(x, x19, x19);
  551. uint[] x37 = Create(); Sqr(x19, 18, x37); Mul(x18, x37, x37);
  552. uint[] x74 = Create(); Sqr(x37, 37, x74); Mul(x37, x74, x74);
  553. uint[] x111 = Create(); Sqr(x74, 37, x111); Mul(x37, x111, x111);
  554. uint[] x222 = Create(); Sqr(x111, 111, x222); Mul(x111, x222, x222);
  555. uint[] x223 = Create(); Sqr(x222, x223); Mul(x, x223, x223);
  556. uint[] t = Create();
  557. Sqr(x223, 223, t);
  558. Mul(t, x222, z);
  559. }
  560. private static void Reduce(uint[] z, int c)
  561. {
  562. uint z15 = z[15];
  563. long t = z15;
  564. z15 &= M28;
  565. t = (t >> 28) + c;
  566. z[8] += (uint)t;
  567. for (int i = 0; i < 15; ++i)
  568. {
  569. t += z[i]; z[i] = (uint)t & M28; t >>= 28;
  570. }
  571. z[15] = z15 + (uint)t;
  572. }
  573. public static void Sqr(uint[] x, uint[] z)
  574. {
  575. uint x0 = x[0];
  576. uint x1 = x[1];
  577. uint x2 = x[2];
  578. uint x3 = x[3];
  579. uint x4 = x[4];
  580. uint x5 = x[5];
  581. uint x6 = x[6];
  582. uint x7 = x[7];
  583. uint u0 = x[8];
  584. uint u1 = x[9];
  585. uint u2 = x[10];
  586. uint u3 = x[11];
  587. uint u4 = x[12];
  588. uint u5 = x[13];
  589. uint u6 = x[14];
  590. uint u7 = x[15];
  591. uint x0_2 = x0 * 2;
  592. uint x1_2 = x1 * 2;
  593. uint x2_2 = x2 * 2;
  594. uint x3_2 = x3 * 2;
  595. uint x4_2 = x4 * 2;
  596. uint x5_2 = x5 * 2;
  597. uint x6_2 = x6 * 2;
  598. uint u0_2 = u0 * 2;
  599. uint u1_2 = u1 * 2;
  600. uint u2_2 = u2 * 2;
  601. uint u3_2 = u3 * 2;
  602. uint u4_2 = u4 * 2;
  603. uint u5_2 = u5 * 2;
  604. uint u6_2 = u6 * 2;
  605. uint s0 = x0 + u0;
  606. uint s1 = x1 + u1;
  607. uint s2 = x2 + u2;
  608. uint s3 = x3 + u3;
  609. uint s4 = x4 + u4;
  610. uint s5 = x5 + u5;
  611. uint s6 = x6 + u6;
  612. uint s7 = x7 + u7;
  613. uint s0_2 = s0 * 2;
  614. uint s1_2 = s1 * 2;
  615. uint s2_2 = s2 * 2;
  616. uint s3_2 = s3 * 2;
  617. uint s4_2 = s4 * 2;
  618. uint s5_2 = s5 * 2;
  619. uint s6_2 = s6 * 2;
  620. uint z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15;
  621. ulong c, d;
  622. ulong f0 = (ulong)x0 * x0;
  623. ulong f8 = (ulong)x7 * x1_2
  624. + (ulong)x6 * x2_2
  625. + (ulong)x5 * x3_2
  626. + (ulong)x4 * x4;
  627. ulong g0 = (ulong)u0 * u0;
  628. ulong g8 = (ulong)u7 * u1_2
  629. + (ulong)u6 * u2_2
  630. + (ulong)u5 * u3_2
  631. + (ulong)u4 * u4;
  632. ulong h0 = (ulong)s0 * s0;
  633. ulong h8 = (ulong)s7 * s1_2
  634. + (ulong)s6 * s2_2
  635. + (ulong)s5 * s3_2
  636. + (ulong)s4 * s4;
  637. c = f0 + g0 + h8 - f8;
  638. z0 = (uint)c & M28; c >>= 28;
  639. d = g8 + h0 - f0 + h8;
  640. z8 = (uint)d & M28; d >>= 28;
  641. ulong f1 = (ulong)x1 * x0_2;
  642. ulong f9 = (ulong)x7 * x2_2
  643. + (ulong)x6 * x3_2
  644. + (ulong)x5 * x4_2;
  645. ulong g1 = (ulong)u1 * u0_2;
  646. ulong g9 = (ulong)u7 * u2_2
  647. + (ulong)u6 * u3_2
  648. + (ulong)u5 * u4_2;
  649. ulong h1 = (ulong)s1 * s0_2;
  650. ulong h9 = (ulong)s7 * s2_2
  651. + (ulong)s6 * s3_2
  652. + (ulong)s5 * s4_2;
  653. c += f1 + g1 + h9 - f9;
  654. z1 = (uint)c & M28; c >>= 28;
  655. d += g9 + h1 - f1 + h9;
  656. z9 = (uint)d & M28; d >>= 28;
  657. ulong f2 = (ulong)x2 * x0_2
  658. + (ulong)x1 * x1;
  659. ulong f10 = (ulong)x7 * x3_2
  660. + (ulong)x6 * x4_2
  661. + (ulong)x5 * x5;
  662. ulong g2 = (ulong)u2 * u0_2
  663. + (ulong)u1 * u1;
  664. ulong g10 = (ulong)u7 * u3_2
  665. + (ulong)u6 * u4_2
  666. + (ulong)u5 * u5;
  667. ulong h2 = (ulong)s2 * s0_2
  668. + (ulong)s1 * s1;
  669. ulong h10 = (ulong)s7 * s3_2
  670. + (ulong)s6 * s4_2
  671. + (ulong)s5 * s5;
  672. c += f2 + g2 + h10 - f10;
  673. z2 = (uint)c & M28; c >>= 28;
  674. d += g10 + h2 - f2 + h10;
  675. z10 = (uint)d & M28; d >>= 28;
  676. ulong f3 = (ulong)x3 * x0_2
  677. + (ulong)x2 * x1_2;
  678. ulong f11 = (ulong)x7 * x4_2
  679. + (ulong)x6 * x5_2;
  680. ulong g3 = (ulong)u3 * u0_2
  681. + (ulong)u2 * u1_2;
  682. ulong g11 = (ulong)u7 * u4_2
  683. + (ulong)u6 * u5_2;
  684. ulong h3 = (ulong)s3 * s0_2
  685. + (ulong)s2 * s1_2;
  686. ulong h11 = (ulong)s7 * s4_2
  687. + (ulong)s6 * s5_2;
  688. c += f3 + g3 + h11 - f11;
  689. z3 = (uint)c & M28; c >>= 28;
  690. d += g11 + h3 - f3 + h11;
  691. z11 = (uint)d & M28; d >>= 28;
  692. ulong f4 = (ulong)x4 * x0_2
  693. + (ulong)x3 * x1_2
  694. + (ulong)x2 * x2;
  695. ulong f12 = (ulong)x7 * x5_2
  696. + (ulong)x6 * x6;
  697. ulong g4 = (ulong)u4 * u0_2
  698. + (ulong)u3 * u1_2
  699. + (ulong)u2 * u2;
  700. ulong g12 = (ulong)u7 * u5_2
  701. + (ulong)u6 * u6;
  702. ulong h4 = (ulong)s4 * s0_2
  703. + (ulong)s3 * s1_2
  704. + (ulong)s2 * s2;
  705. ulong h12 = (ulong)s7 * s5_2
  706. + (ulong)s6 * s6;
  707. c += f4 + g4 + h12 - f12;
  708. z4 = (uint)c & M28; c >>= 28;
  709. d += g12 + h4 - f4 + h12;
  710. z12 = (uint)d & M28; d >>= 28;
  711. ulong f5 = (ulong)x5 * x0_2
  712. + (ulong)x4 * x1_2
  713. + (ulong)x3 * x2_2;
  714. ulong f13 = (ulong)x7 * x6_2;
  715. ulong g5 = (ulong)u5 * u0_2
  716. + (ulong)u4 * u1_2
  717. + (ulong)u3 * u2_2;
  718. ulong g13 = (ulong)u7 * u6_2;
  719. ulong h5 = (ulong)s5 * s0_2
  720. + (ulong)s4 * s1_2
  721. + (ulong)s3 * s2_2;
  722. ulong h13 = (ulong)s7 * s6_2;
  723. c += f5 + g5 + h13 - f13;
  724. z5 = (uint)c & M28; c >>= 28;
  725. d += g13 + h5 - f5 + h13;
  726. z13 = (uint)d & M28; d >>= 28;
  727. ulong f6 = (ulong)x6 * x0_2
  728. + (ulong)x5 * x1_2
  729. + (ulong)x4 * x2_2
  730. + (ulong)x3 * x3;
  731. ulong f14 = (ulong)x7 * x7;
  732. ulong g6 = (ulong)u6 * u0_2
  733. + (ulong)u5 * u1_2
  734. + (ulong)u4 * u2_2
  735. + (ulong)u3 * u3;
  736. ulong g14 = (ulong)u7 * u7;
  737. ulong h6 = (ulong)s6 * s0_2
  738. + (ulong)s5 * s1_2
  739. + (ulong)s4 * s2_2
  740. + (ulong)s3 * s3;
  741. ulong h14 = (ulong)s7 * s7;
  742. c += f6 + g6 + h14 - f14;
  743. z6 = (uint)c & M28; c >>= 28;
  744. d += g14 + h6 - f6 + h14;
  745. z14 = (uint)d & M28; d >>= 28;
  746. ulong f7 = (ulong)x7 * x0_2
  747. + (ulong)x6 * x1_2
  748. + (ulong)x5 * x2_2
  749. + (ulong)x4 * x3_2;
  750. ulong g7 = (ulong)u7 * u0_2
  751. + (ulong)u6 * u1_2
  752. + (ulong)u5 * u2_2
  753. + (ulong)u4 * u3_2;
  754. ulong h7 = (ulong)s7 * s0_2
  755. + (ulong)s6 * s1_2
  756. + (ulong)s5 * s2_2
  757. + (ulong)s4 * s3_2;
  758. c += f7 + g7;
  759. z7 = (uint)c & M28; c >>= 28;
  760. d += h7 - f7;
  761. z15 = (uint)d & M28; d >>= 28;
  762. c += d;
  763. c += z8;
  764. z8 = (uint)c & M28; c >>= 28;
  765. d += z0;
  766. z0 = (uint)d & M28; d >>= 28;
  767. z9 += (uint)c;
  768. z1 += (uint)d;
  769. z[0] = z0;
  770. z[1] = z1;
  771. z[2] = z2;
  772. z[3] = z3;
  773. z[4] = z4;
  774. z[5] = z5;
  775. z[6] = z6;
  776. z[7] = z7;
  777. z[8] = z8;
  778. z[9] = z9;
  779. z[10] = z10;
  780. z[11] = z11;
  781. z[12] = z12;
  782. z[13] = z13;
  783. z[14] = z14;
  784. z[15] = z15;
  785. }
  786. public static void Sqr(uint[] x, int n, uint[] z)
  787. {
  788. Debug.Assert(n > 0);
  789. Sqr(x, z);
  790. while (--n > 0)
  791. {
  792. Sqr(z, z);
  793. }
  794. }
  795. public static bool SqrtRatioVar(uint[] u, uint[] v, uint[] z)
  796. {
  797. uint[] u3v = Create();
  798. uint[] u5v3 = Create();
  799. Sqr(u, u3v);
  800. Mul(u3v, v, u3v);
  801. Sqr(u3v, u5v3);
  802. Mul(u3v, u, u3v);
  803. Mul(u5v3, u, u5v3);
  804. Mul(u5v3, v, u5v3);
  805. uint[] x = Create();
  806. PowPm3d4(u5v3, x);
  807. Mul(x, u3v, x);
  808. uint[] t = Create();
  809. Sqr(x, t);
  810. Mul(t, v, t);
  811. Sub(u, t, t);
  812. Normalize(t);
  813. if (IsZeroVar(t))
  814. {
  815. Copy(x, 0, z, 0);
  816. return true;
  817. }
  818. return false;
  819. }
  820. public static void Sub(uint[] x, uint[] y, uint[] z)
  821. {
  822. uint x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7];
  823. uint x8 = x[8], x9 = x[9], x10 = x[10], x11 = x[11], x12 = x[12], x13 = x[13], x14 = x[14], x15 = x[15];
  824. uint y0 = y[0], y1 = y[1], y2 = y[2], y3 = y[3], y4 = y[4], y5 = y[5], y6 = y[6], y7 = y[7];
  825. uint y8 = y[8], y9 = y[9], y10 = y[10], y11 = y[11], y12 = y[12], y13 = y[13], y14 = y[14], y15 = y[15];
  826. uint z0 = x0 + 0x1FFFFFFEU - y0;
  827. uint z1 = x1 + 0x1FFFFFFEU - y1;
  828. uint z2 = x2 + 0x1FFFFFFEU - y2;
  829. uint z3 = x3 + 0x1FFFFFFEU - y3;
  830. uint z4 = x4 + 0x1FFFFFFEU - y4;
  831. uint z5 = x5 + 0x1FFFFFFEU - y5;
  832. uint z6 = x6 + 0x1FFFFFFEU - y6;
  833. uint z7 = x7 + 0x1FFFFFFEU - y7;
  834. uint z8 = x8 + 0x1FFFFFFCU - y8;
  835. uint z9 = x9 + 0x1FFFFFFEU - y9;
  836. uint z10 = x10 + 0x1FFFFFFEU - y10;
  837. uint z11 = x11 + 0x1FFFFFFEU - y11;
  838. uint z12 = x12 + 0x1FFFFFFEU - y12;
  839. uint z13 = x13 + 0x1FFFFFFEU - y13;
  840. uint z14 = x14 + 0x1FFFFFFEU - y14;
  841. uint z15 = x15 + 0x1FFFFFFEU - y15;
  842. z2 += z1 >> 28; z1 &= M28;
  843. z6 += z5 >> 28; z5 &= M28;
  844. z10 += z9 >> 28; z9 &= M28;
  845. z14 += z13 >> 28; z13 &= M28;
  846. z3 += z2 >> 28; z2 &= M28;
  847. z7 += z6 >> 28; z6 &= M28;
  848. z11 += z10 >> 28; z10 &= M28;
  849. z15 += z14 >> 28; z14 &= M28;
  850. uint t = z15 >> 28; z15 &= M28;
  851. z0 += t;
  852. z8 += t;
  853. z4 += z3 >> 28; z3 &= M28;
  854. z8 += z7 >> 28; z7 &= M28;
  855. z12 += z11 >> 28; z11 &= M28;
  856. z1 += z0 >> 28; z0 &= M28;
  857. z5 += z4 >> 28; z4 &= M28;
  858. z9 += z8 >> 28; z8 &= M28;
  859. z13 += z12 >> 28; z12 &= M28;
  860. z[0] = z0;
  861. z[1] = z1;
  862. z[2] = z2;
  863. z[3] = z3;
  864. z[4] = z4;
  865. z[5] = z5;
  866. z[6] = z6;
  867. z[7] = z7;
  868. z[8] = z8;
  869. z[9] = z9;
  870. z[10] = z10;
  871. z[11] = z11;
  872. z[12] = z12;
  873. z[13] = z13;
  874. z[14] = z14;
  875. z[15] = z15;
  876. }
  877. public static void Zero(uint[] z)
  878. {
  879. for (int i = 0; i < Size; ++i)
  880. {
  881. z[i] = 0;
  882. }
  883. }
  884. }
  885. }
  886. #pragma warning restore
  887. #endif