X448Field.cs 36 KB

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