Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

599 linhas
18 KiB

  1. package cln16sidh
  2. //------------------------------------------------------------------------------
  3. // Extension Field
  4. //------------------------------------------------------------------------------
  5. // Represents an element of the extension field F_{p^2}.
  6. type ExtensionFieldElement struct {
  7. // This field element is in Montgomery form, so that the value `a` is
  8. // represented by `aR mod p`.
  9. a fp751Element
  10. // This field element is in Montgomery form, so that the value `b` is
  11. // represented by `bR mod p`.
  12. b fp751Element
  13. }
  14. var zeroExtensionField = ExtensionFieldElement{
  15. a: fp751Element{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
  16. b: fp751Element{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
  17. }
  18. var oneExtensionField = ExtensionFieldElement{
  19. a: fp751Element{0x249ad, 0x0, 0x0, 0x0, 0x0, 0x8310000000000000, 0x5527b1e4375c6c66, 0x697797bf3f4f24d0, 0xc89db7b2ac5c4e2e, 0x4ca4b439d2076956, 0x10f7926c7512c7e9, 0x2d5b24bce5e2},
  20. b: fp751Element{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
  21. }
  22. // Set dest = 0.
  23. //
  24. // Returns dest to allow chaining operations.
  25. func (dest *ExtensionFieldElement) Zero() *ExtensionFieldElement {
  26. *dest = zeroExtensionField
  27. return dest
  28. }
  29. // Set dest = 1.
  30. //
  31. // Returns dest to allow chaining operations.
  32. func (dest *ExtensionFieldElement) One() *ExtensionFieldElement {
  33. *dest = oneExtensionField
  34. return dest
  35. }
  36. // Set dest = lhs * rhs.
  37. //
  38. // Allowed to overlap lhs or rhs with dest.
  39. //
  40. // Returns dest to allow chaining operations.
  41. func (dest *ExtensionFieldElement) Mul(lhs, rhs *ExtensionFieldElement) *ExtensionFieldElement {
  42. // Let (a,b,c,d) = (lhs.a,lhs.b,rhs.a,rhs.b).
  43. a := &lhs.a
  44. b := &lhs.b
  45. c := &rhs.a
  46. d := &rhs.b
  47. // We want to compute
  48. //
  49. // (a + bi)*(c + di) = (a*c - b*d) + (a*d + b*c)i
  50. //
  51. // Use Karatsuba's trick: note that
  52. //
  53. // (b - a)*(c - d) = (b*c + a*d) - a*c - b*d
  54. //
  55. // so (a*d + b*c) = (b-a)*(c-d) + a*c + b*d.
  56. var ac, bd fp751X2
  57. fp751Mul(&ac, a, c) // = a*c*R*R
  58. fp751Mul(&bd, b, d) // = b*d*R*R
  59. var b_minus_a, c_minus_d fp751Element
  60. fp751SubReduced(&b_minus_a, b, a) // = (b-a)*R
  61. fp751SubReduced(&c_minus_d, c, d) // = (c-d)*R
  62. var ad_plus_bc fp751X2
  63. fp751Mul(&ad_plus_bc, &b_minus_a, &c_minus_d) // = (b-a)*(c-d)*R*R
  64. fp751X2AddLazy(&ad_plus_bc, &ad_plus_bc, &ac) // = ((b-a)*(c-d) + a*c)*R*R
  65. fp751X2AddLazy(&ad_plus_bc, &ad_plus_bc, &bd) // = ((b-a)*(c-d) + a*c + b*d)*R*R
  66. fp751MontgomeryReduce(&dest.b, &ad_plus_bc) // = (a*d + b*c)*R mod p
  67. var ac_minus_bd fp751X2
  68. fp751X2SubLazy(&ac_minus_bd, &ac, &bd) // = (a*c - b*d)*R*R
  69. fp751MontgomeryReduce(&dest.a, &ac_minus_bd) // = (a*c - b*d)*R mod p
  70. return dest
  71. }
  72. // Set dest = -x
  73. //
  74. // Allowed to overlap dest with x.
  75. //
  76. // Returns dest to allow chaining operations.
  77. func (dest *ExtensionFieldElement) Neg(x *ExtensionFieldElement) *ExtensionFieldElement {
  78. dest.Sub(&zeroExtensionField, x)
  79. return dest
  80. }
  81. // Set dest = 1/x
  82. //
  83. // Allowed to overlap dest with x.
  84. //
  85. // Returns dest to allow chaining operations.
  86. func (dest *ExtensionFieldElement) Inv(x *ExtensionFieldElement) *ExtensionFieldElement {
  87. a := &x.a
  88. b := &x.b
  89. // We want to compute
  90. //
  91. // 1 1 (a - bi) (a - bi)
  92. // -------- = -------- -------- = -----------
  93. // (a + bi) (a + bi) (a - bi) (a^2 + b^2)
  94. //
  95. // Letting c = 1/(a^2 + b^2), this is
  96. //
  97. // 1/(a+bi) = a*c - b*ci.
  98. var asq_plus_bsq PrimeFieldElement
  99. var asq, bsq fp751X2
  100. fp751Mul(&asq, a, a) // = a*a*R*R
  101. fp751Mul(&bsq, b, b) // = b*b*R*R
  102. fp751X2AddLazy(&asq, &asq, &bsq) // = (a^2 + b^2)*R*R
  103. fp751MontgomeryReduce(&asq_plus_bsq.a, &asq) // = (a^2 + b^2)*R mod p
  104. // Now asq_plus_bsq = a^2 + b^2
  105. var asq_plus_bsq_inv PrimeFieldElement
  106. asq_plus_bsq_inv.Inv(&asq_plus_bsq)
  107. c := &asq_plus_bsq_inv.a
  108. var ac fp751X2
  109. fp751Mul(&ac, a, c)
  110. fp751MontgomeryReduce(&dest.a, &ac)
  111. var minus_b fp751Element
  112. fp751SubReduced(&minus_b, &minus_b, b)
  113. var minus_bc fp751X2
  114. fp751Mul(&minus_bc, &minus_b, c)
  115. fp751MontgomeryReduce(&dest.b, &minus_bc)
  116. return dest
  117. }
  118. // Set (y1, y2, y3) = (1/x1, 1/x2, 1/x3).
  119. //
  120. // All xi, yi must be distinct.
  121. func ExtensionFieldBatch3Inv(x1, x2, x3, y1, y2, y3 *ExtensionFieldElement) {
  122. var x1x2, t ExtensionFieldElement
  123. x1x2.Mul(x1, x2) // x1*x2
  124. t.Mul(&x1x2, x3).Inv(&t) // 1/(x1*x2*x3)
  125. y1.Mul(&t, x2).Mul(y1, x3) // 1/x1
  126. y2.Mul(&t, x1).Mul(y2, x3) // 1/x2
  127. y3.Mul(&t, &x1x2) // 1/x3
  128. }
  129. // Set dest = x * x
  130. //
  131. // Allowed to overlap dest with x.
  132. //
  133. // Returns dest to allow chaining operations.
  134. func (dest *ExtensionFieldElement) Square(x *ExtensionFieldElement) *ExtensionFieldElement {
  135. a := &x.a
  136. b := &x.b
  137. // We want to compute
  138. //
  139. // (a + bi)*(a + bi) = (a^2 - b^2) + 2abi.
  140. var a2, a_plus_b, a_minus_b fp751Element
  141. fp751AddReduced(&a2, a, a) // = a*R + a*R = 2*a*R
  142. fp751AddReduced(&a_plus_b, a, b) // = a*R + b*R = (a+b)*R
  143. fp751SubReduced(&a_minus_b, a, b) // = a*R - b*R = (a-b)*R
  144. var asq_minus_bsq, ab2 fp751X2
  145. fp751Mul(&asq_minus_bsq, &a_plus_b, &a_minus_b) // = (a+b)*(a-b)*R*R = (a^2 - b^2)*R*R
  146. fp751Mul(&ab2, &a2, b) // = 2*a*b*R*R
  147. fp751MontgomeryReduce(&dest.a, &asq_minus_bsq) // = (a^2 - b^2)*R mod p
  148. fp751MontgomeryReduce(&dest.b, &ab2) // = 2*a*b*R mod p
  149. return dest
  150. }
  151. // Set dest = lhs + rhs.
  152. //
  153. // Allowed to overlap lhs or rhs with dest.
  154. //
  155. // Returns dest to allow chaining operations.
  156. func (dest *ExtensionFieldElement) Add(lhs, rhs *ExtensionFieldElement) *ExtensionFieldElement {
  157. fp751AddReduced(&dest.a, &lhs.a, &rhs.a)
  158. fp751AddReduced(&dest.b, &lhs.b, &rhs.b)
  159. return dest
  160. }
  161. // Set dest = lhs - rhs.
  162. //
  163. // Allowed to overlap lhs or rhs with dest.
  164. //
  165. // Returns dest to allow chaining operations.
  166. func (dest *ExtensionFieldElement) Sub(lhs, rhs *ExtensionFieldElement) *ExtensionFieldElement {
  167. fp751SubReduced(&dest.a, &lhs.a, &rhs.a)
  168. fp751SubReduced(&dest.b, &lhs.b, &rhs.b)
  169. return dest
  170. }
  171. // If choice = 1u8, set (x,y) = (y,x). If choice = 0u8, set (x,y) = (x,y).
  172. //
  173. // Returns dest to allow chaining operations.
  174. func ExtensionFieldConditionalSwap(x, y *ExtensionFieldElement, choice uint8) {
  175. fp751ConditionalSwap(&x.a, &y.a, choice)
  176. fp751ConditionalSwap(&x.b, &y.b, choice)
  177. }
  178. // Set dest = if choice == 0 { x } else { y }, in constant time.
  179. //
  180. // Can overlap z with x or y or both.
  181. //
  182. // Returns dest to allow chaining operations.
  183. func (dest *ExtensionFieldElement) ConditionalAssign(x, y *ExtensionFieldElement, choice uint8) *ExtensionFieldElement {
  184. fp751ConditionalAssign(&dest.a, &x.a, &y.a, choice)
  185. fp751ConditionalAssign(&dest.b, &x.b, &y.b, choice)
  186. return dest
  187. }
  188. // Returns true if lhs = rhs. Takes variable time.
  189. func (lhs *ExtensionFieldElement) VartimeEq(rhs *ExtensionFieldElement) bool {
  190. return lhs.a.vartimeEq(rhs.a) && lhs.b.vartimeEq(rhs.b)
  191. }
  192. // Convert the input to wire format.
  193. //
  194. // The output byte slice must be at least 188 bytes long.
  195. func (x *ExtensionFieldElement) ToBytes(output []byte) {
  196. if len(output) < 188 {
  197. panic("output byte slice too short, need 188 bytes")
  198. }
  199. x.a.toBytesFromMontgomeryForm(output[0:94])
  200. x.b.toBytesFromMontgomeryForm(output[94:188])
  201. }
  202. // Read 188 bytes into the given ExtensionFieldElement.
  203. //
  204. // It is an error to call this function if the input byte slice is less than 188 bytes long.
  205. func (x *ExtensionFieldElement) FromBytes(input []byte) {
  206. if len(input) < 188 {
  207. panic("input byte slice too short, need 188 bytes")
  208. }
  209. x.a.montgomeryFormFromBytes(input[:94])
  210. x.b.montgomeryFormFromBytes(input[94:188])
  211. }
  212. //------------------------------------------------------------------------------
  213. // Prime Field
  214. //------------------------------------------------------------------------------
  215. // Represents an element of the prime field F_p.
  216. type PrimeFieldElement struct {
  217. // This field element is in Montgomery form, so that the value `a` is
  218. // represented by `aR mod p`.
  219. a fp751Element
  220. }
  221. var zeroPrimeField = PrimeFieldElement{
  222. a: fp751Element{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
  223. }
  224. var onePrimeField = PrimeFieldElement{
  225. a: fp751Element{0x249ad, 0x0, 0x0, 0x0, 0x0, 0x8310000000000000, 0x5527b1e4375c6c66, 0x697797bf3f4f24d0, 0xc89db7b2ac5c4e2e, 0x4ca4b439d2076956, 0x10f7926c7512c7e9, 0x2d5b24bce5e2},
  226. }
  227. // Set dest = 0.
  228. //
  229. // Returns dest to allow chaining operations.
  230. func (dest *PrimeFieldElement) Zero() *PrimeFieldElement {
  231. *dest = zeroPrimeField
  232. return dest
  233. }
  234. // Set dest = 1.
  235. //
  236. // Returns dest to allow chaining operations.
  237. func (dest *PrimeFieldElement) One() *PrimeFieldElement {
  238. *dest = onePrimeField
  239. return dest
  240. }
  241. // Set dest to x.
  242. //
  243. // Returns dest to allow chaining operations.
  244. func (dest *PrimeFieldElement) SetUint64(x uint64) *PrimeFieldElement {
  245. var xRR fp751X2
  246. dest.a = fp751Element{} // = 0
  247. dest.a[0] = x // = x
  248. fp751Mul(&xRR, &dest.a, &montgomeryRsq) // = x*R*R
  249. fp751MontgomeryReduce(&dest.a, &xRR) // = x*R mod p
  250. return dest
  251. }
  252. // Set dest = lhs * rhs.
  253. //
  254. // Allowed to overlap lhs or rhs with dest.
  255. //
  256. // Returns dest to allow chaining operations.
  257. func (dest *PrimeFieldElement) Mul(lhs, rhs *PrimeFieldElement) *PrimeFieldElement {
  258. a := &lhs.a // = a*R
  259. b := &rhs.a // = b*R
  260. var ab fp751X2
  261. fp751Mul(&ab, a, b) // = a*b*R*R
  262. fp751MontgomeryReduce(&dest.a, &ab) // = a*b*R mod p
  263. return dest
  264. }
  265. // Set dest = x^(2^k), for k >= 1, by repeated squarings.
  266. //
  267. // Allowed to overlap x with dest.
  268. //
  269. // Returns dest to allow chaining operations.
  270. func (dest *PrimeFieldElement) Pow2k(x *PrimeFieldElement, k uint8) *PrimeFieldElement {
  271. dest.Square(x)
  272. for i := uint8(1); i < k; i++ {
  273. dest.Square(dest)
  274. }
  275. return dest
  276. }
  277. // Set dest = x^2
  278. //
  279. // Allowed to overlap x with dest.
  280. //
  281. // Returns dest to allow chaining operations.
  282. func (dest *PrimeFieldElement) Square(x *PrimeFieldElement) *PrimeFieldElement {
  283. a := &x.a // = a*R
  284. b := &x.a // = b*R
  285. var ab fp751X2
  286. fp751Mul(&ab, a, b) // = a*b*R*R
  287. fp751MontgomeryReduce(&dest.a, &ab) // = a*b*R mod p
  288. return dest
  289. }
  290. // Set dest = -x
  291. //
  292. // Allowed to overlap x with dest.
  293. //
  294. // Returns dest to allow chaining operations.
  295. func (dest *PrimeFieldElement) Neg(x *PrimeFieldElement) *PrimeFieldElement {
  296. dest.Sub(&zeroPrimeField, x)
  297. return dest
  298. }
  299. // Set dest = lhs + rhs.
  300. //
  301. // Allowed to overlap lhs or rhs with dest.
  302. //
  303. // Returns dest to allow chaining operations.
  304. func (dest *PrimeFieldElement) Add(lhs, rhs *PrimeFieldElement) *PrimeFieldElement {
  305. fp751AddReduced(&dest.a, &lhs.a, &rhs.a)
  306. return dest
  307. }
  308. // Set dest = lhs - rhs.
  309. //
  310. // Allowed to overlap lhs or rhs with dest.
  311. //
  312. // Returns dest to allow chaining operations.
  313. func (dest *PrimeFieldElement) Sub(lhs, rhs *PrimeFieldElement) *PrimeFieldElement {
  314. fp751SubReduced(&dest.a, &lhs.a, &rhs.a)
  315. return dest
  316. }
  317. // Returns true if lhs = rhs. Takes variable time.
  318. func (lhs *PrimeFieldElement) VartimeEq(rhs *PrimeFieldElement) bool {
  319. return lhs.a.vartimeEq(rhs.a)
  320. }
  321. // If choice = 1u8, set (x,y) = (y,x). If choice = 0u8, set (x,y) = (x,y).
  322. //
  323. // Returns dest to allow chaining operations.
  324. func PrimeFieldConditionalSwap(x, y *PrimeFieldElement, choice uint8) {
  325. fp751ConditionalSwap(&x.a, &y.a, choice)
  326. }
  327. // Set dest = if choice == 0 { x } else { y }, in constant time.
  328. //
  329. // Can overlap z with x or y or both.
  330. //
  331. // Returns dest to allow chaining operations.
  332. func (dest *PrimeFieldElement) ConditionalAssign(x, y *PrimeFieldElement, choice uint8) *PrimeFieldElement {
  333. fp751ConditionalAssign(&dest.a, &x.a, &y.a, choice)
  334. return dest
  335. }
  336. // Set dest = sqrt(x), if x is a square. If x is nonsquare dest is undefined.
  337. //
  338. // Allowed to overlap x with dest.
  339. //
  340. // Returns dest to allow chaining operations.
  341. func (dest *PrimeFieldElement) Sqrt(x *PrimeFieldElement) *PrimeFieldElement {
  342. tmp_x := *x // Copy x in case dest == x
  343. // Since x is assumed to be square, x = y^2
  344. dest.P34(x) // dest = (y^2)^((p-3)/4) = y^((p-3)/2)
  345. dest.Mul(dest, &tmp_x) // dest = y^2 * y^((p-3)/2) = y^((p+1)/2)
  346. // Now dest^2 = y^(p+1) = y^2 = x, so dest = sqrt(x)
  347. return dest
  348. }
  349. // Set dest = 1/x.
  350. //
  351. // Allowed to overlap x with dest.
  352. //
  353. // Returns dest to allow chaining operations.
  354. func (dest *PrimeFieldElement) Inv(x *PrimeFieldElement) *PrimeFieldElement {
  355. tmp_x := *x // Copy x in case dest == x
  356. dest.Square(x) // dest = x^2
  357. dest.P34(dest) // dest = (x^2)^((p-3)/4) = x^((p-3)/2)
  358. dest.Square(dest) // dest = x^(p-3)
  359. dest.Mul(dest, &tmp_x) // dest = x^(p-2)
  360. return dest
  361. }
  362. // Set dest = x^((p-3)/4). If x is square, this is 1/sqrt(x).
  363. //
  364. // Allowed to overlap x with dest.
  365. //
  366. // Returns dest to allow chaining operations.
  367. func (dest *PrimeFieldElement) P34(x *PrimeFieldElement) *PrimeFieldElement {
  368. // Sliding-window strategy computed with Sage, awk, sed, and tr.
  369. //
  370. // This performs sum(powStrategy) = 744 squarings and len(mulStrategy)
  371. // = 137 multiplications, in addition to 1 squaring and 15
  372. // multiplications to build a lookup table.
  373. //
  374. // In total this is 745 squarings, 152 multiplications. Since squaring
  375. // is not implemented for the prime field, this is 897 multiplications
  376. // in total.
  377. powStrategy := [137]uint8{5, 7, 6, 2, 10, 4, 6, 9, 8, 5, 9, 4, 7, 5, 5, 4, 8, 3, 9, 5, 5, 4, 10, 4, 6, 6, 6, 5, 8, 9, 3, 4, 9, 4, 5, 6, 6, 2, 9, 4, 5, 5, 5, 7, 7, 9, 4, 6, 4, 8, 5, 8, 6, 6, 2, 9, 7, 4, 8, 8, 8, 4, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2}
  378. mulStrategy := [137]uint8{31, 23, 21, 1, 31, 7, 7, 7, 9, 9, 19, 15, 23, 23, 11, 7, 25, 5, 21, 17, 11, 5, 17, 7, 11, 9, 23, 9, 1, 19, 5, 3, 25, 15, 11, 29, 31, 1, 29, 11, 13, 9, 11, 27, 13, 19, 15, 31, 3, 29, 23, 31, 25, 11, 1, 21, 19, 15, 15, 21, 29, 13, 23, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 3}
  379. initialMul := uint8(27)
  380. // Build a lookup table of odd multiples of x.
  381. lookup := [16]PrimeFieldElement{}
  382. xx := &PrimeFieldElement{}
  383. xx.Square(x) // Set xx = x^2
  384. lookup[0] = *x
  385. for i := 1; i < 16; i++ {
  386. lookup[i].Mul(&lookup[i-1], xx)
  387. }
  388. // Now lookup = {x, x^3, x^5, ... }
  389. // so that lookup[i] = x^{2*i + 1}
  390. // so that lookup[k/2] = x^k, for odd k
  391. *dest = lookup[initialMul/2]
  392. for i := uint8(0); i < 137; i++ {
  393. dest.Pow2k(dest, powStrategy[i])
  394. dest.Mul(dest, &lookup[mulStrategy[i]/2])
  395. }
  396. return dest
  397. }
  398. //------------------------------------------------------------------------------
  399. // Internals
  400. //------------------------------------------------------------------------------
  401. const fp751NumWords = 12
  402. // (2^768) mod p.
  403. // This can't be a constant because Go doesn't allow array constants, so try
  404. // not to modify it.
  405. var montgomeryR = fp751Element{149933, 0, 0, 0, 0, 9444048418595930112, 6136068611055053926, 7599709743867700432, 14455912356952952366, 5522737203492907350, 1222606818372667369, 49869481633250}
  406. // (2^768)^2 mod p
  407. // This can't be a constant because Go doesn't allow array constants, so try
  408. // not to modify it.
  409. var montgomeryRsq = fp751Element{2535603850726686808, 15780896088201250090, 6788776303855402382, 17585428585582356230, 5274503137951975249, 2266259624764636289, 11695651972693921304, 13072885652150159301, 4908312795585420432, 6229583484603254826, 488927695601805643, 72213483953973}
  410. // Internal representation of an element of the base field F_p.
  411. //
  412. // This type is distinct from PrimeFieldElement in that no particular meaning
  413. // is assigned to the representation -- it could represent an element in
  414. // Montgomery form, or not. Tracking the meaning of the field element is left
  415. // to higher types.
  416. type fp751Element [fp751NumWords]uint64
  417. // Represents an intermediate product of two elements of the base field F_p.
  418. type fp751X2 [2 * fp751NumWords]uint64
  419. // If choice = 0, leave x,y unchanged. If choice = 1, set x,y = y,x.
  420. // This function executes in constant time.
  421. //go:noescape
  422. func fp751ConditionalSwap(x, y *fp751Element, choice uint8)
  423. // If choice = 0, set z = x. If choice = 1, set z = y.
  424. // This function executes in constant time.
  425. //
  426. // Can overlap z with x or y or both.
  427. //go:noescape
  428. func fp751ConditionalAssign(z, x, y *fp751Element, choice uint8)
  429. // Compute z = x + y (mod p).
  430. //go:noescape
  431. func fp751AddReduced(z, x, y *fp751Element)
  432. // Compute z = x - y (mod p).
  433. //go:noescape
  434. func fp751SubReduced(z, x, y *fp751Element)
  435. // Compute z = x + y, without reducing mod p.
  436. //go:noescape
  437. func fp751AddLazy(z, x, y *fp751Element)
  438. // Compute z = x + y, without reducing mod p.
  439. //go:noescape
  440. func fp751X2AddLazy(z, x, y *fp751X2)
  441. // Compute z = x - y, without reducing mod p.
  442. //go:noescape
  443. func fp751X2SubLazy(z, x, y *fp751X2)
  444. // Compute z = x * y.
  445. //go:noescape
  446. func fp751Mul(z *fp751X2, x, y *fp751Element)
  447. // Perform Montgomery reduction: set z = x R^{-1} (mod p).
  448. // Destroys the input value.
  449. //go:noescape
  450. func fp751MontgomeryReduce(z *fp751Element, x *fp751X2)
  451. // Reduce a field element in [0, 2*p) to one in [0,p).
  452. //go:noescape
  453. func fp751StrongReduce(x *fp751Element)
  454. func (x fp751Element) vartimeEq(y fp751Element) bool {
  455. fp751StrongReduce(&x)
  456. fp751StrongReduce(&y)
  457. eq := true
  458. for i := 0; i < fp751NumWords; i++ {
  459. eq = (x[i] == y[i]) && eq
  460. }
  461. return eq
  462. }
  463. // Read an fp751Element from little-endian bytes and convert to Montgomery form.
  464. //
  465. // The input byte slice must be at least 94 bytes long.
  466. func (x *fp751Element) montgomeryFormFromBytes(input []byte) {
  467. if len(input) < 94 {
  468. panic("input byte slice too short")
  469. }
  470. var a fp751Element
  471. for i := 0; i < 94; i++ {
  472. // set i = j*8 + k
  473. j := i / 8
  474. k := uint64(i % 8)
  475. a[j] |= uint64(input[i]) << (8 * k)
  476. }
  477. var aRR fp751X2
  478. fp751Mul(&aRR, &a, &montgomeryRsq) // = a*R*R
  479. fp751MontgomeryReduce(x, &aRR) // = a*R mod p
  480. }
  481. // Given an fp751Element in Montgomery form, convert to little-endian bytes.
  482. //
  483. // The output byte slice must be at least 94 bytes long.
  484. func (x *fp751Element) toBytesFromMontgomeryForm(output []byte) {
  485. if len(output) < 94 {
  486. panic("output byte slice too short")
  487. }
  488. var a fp751Element
  489. var aR fp751X2
  490. copy(aR[:], x[:]) // = a*R
  491. fp751MontgomeryReduce(&a, &aR) // = a mod p in [0, 2p)
  492. fp751StrongReduce(&a) // = a mod p in [0, p)
  493. // 8*12 = 96, but we drop the last two bytes since p is 751 < 752=94*8 bits.
  494. for i := 0; i < 94; i++ {
  495. // set i = j*8 + k
  496. j := i / 8
  497. k := uint64(i % 8)
  498. // Need parens because Go's operator precedence would interpret
  499. // a[j] >> 8*k as (a[j] >> 8) * k
  500. output[i] = byte(a[j] >> (8 * k))
  501. }
  502. }