You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

406 line
13 KiB

  1. package p751toolbox
  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. // 2*p751
  23. var p751x2 = Fp751Element{
  24. 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
  25. 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xDD5FFFFFFFFFFFFF,
  26. 0xC7D92D0A93F0F151, 0xB52B363427EF98ED, 0x109D30CFADD7D0ED,
  27. 0x0AC56A08B964AE90, 0x1C25213F2F75B8CD, 0x0000DFCBAA83EE38}
  28. // p751
  29. var p751 = Fp751Element{
  30. 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
  31. 0xffffffffffffffff, 0xffffffffffffffff, 0xeeafffffffffffff,
  32. 0xe3ec968549f878a8, 0xda959b1a13f7cc76, 0x084e9867d6ebe876,
  33. 0x8562b5045cb25748, 0x0e12909f97badc66, 0x00006fe5d541f71c}
  34. // p751 + 1
  35. var p751p1 = Fp751Element{
  36. 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
  37. 0x0000000000000000, 0x0000000000000000, 0xeeb0000000000000,
  38. 0xe3ec968549f878a8, 0xda959b1a13f7cc76, 0x084e9867d6ebe876,
  39. 0x8562b5045cb25748, 0x0e12909f97badc66, 0x00006fe5d541f71c}
  40. // Set dest = 0.
  41. //
  42. // Returns dest to allow chaining operations.
  43. func (dest *ExtensionFieldElement) Zero() *ExtensionFieldElement {
  44. *dest = zeroExtensionField
  45. return dest
  46. }
  47. // Set dest = 1.
  48. //
  49. // Returns dest to allow chaining operations.
  50. func (dest *ExtensionFieldElement) One() *ExtensionFieldElement {
  51. *dest = oneExtensionField
  52. return dest
  53. }
  54. // Set dest = lhs * rhs.
  55. //
  56. // Allowed to overlap lhs or rhs with dest.
  57. //
  58. // Returns dest to allow chaining operations.
  59. func (dest *ExtensionFieldElement) Mul(lhs, rhs *ExtensionFieldElement) *ExtensionFieldElement {
  60. // Let (a,b,c,d) = (lhs.a,lhs.b,rhs.a,rhs.b).
  61. a := &lhs.A
  62. b := &lhs.B
  63. c := &rhs.A
  64. d := &rhs.B
  65. // We want to compute
  66. //
  67. // (a + bi)*(c + di) = (a*c - b*d) + (a*d + b*c)i
  68. //
  69. // Use Karatsuba's trick: note that
  70. //
  71. // (b - a)*(c - d) = (b*c + a*d) - a*c - b*d
  72. //
  73. // so (a*d + b*c) = (b-a)*(c-d) + a*c + b*d.
  74. var ac, bd fp751X2
  75. fp751Mul(&ac, a, c) // = a*c*R*R
  76. fp751Mul(&bd, b, d) // = b*d*R*R
  77. var b_minus_a, c_minus_d Fp751Element
  78. fp751SubReduced(&b_minus_a, b, a) // = (b-a)*R
  79. fp751SubReduced(&c_minus_d, c, d) // = (c-d)*R
  80. var ad_plus_bc fp751X2
  81. fp751Mul(&ad_plus_bc, &b_minus_a, &c_minus_d) // = (b-a)*(c-d)*R*R
  82. fp751X2AddLazy(&ad_plus_bc, &ad_plus_bc, &ac) // = ((b-a)*(c-d) + a*c)*R*R
  83. fp751X2AddLazy(&ad_plus_bc, &ad_plus_bc, &bd) // = ((b-a)*(c-d) + a*c + b*d)*R*R
  84. fp751MontgomeryReduce(&dest.B, &ad_plus_bc) // = (a*d + b*c)*R mod p
  85. var ac_minus_bd fp751X2
  86. fp751X2SubLazy(&ac_minus_bd, &ac, &bd) // = (a*c - b*d)*R*R
  87. fp751MontgomeryReduce(&dest.A, &ac_minus_bd) // = (a*c - b*d)*R mod p
  88. return dest
  89. }
  90. // Set dest = 1/x
  91. //
  92. // Allowed to overlap dest with x.
  93. //
  94. // Returns dest to allow chaining operations.
  95. func (dest *ExtensionFieldElement) Inv(x *ExtensionFieldElement) *ExtensionFieldElement {
  96. a := &x.A
  97. b := &x.B
  98. // We want to compute
  99. //
  100. // 1 1 (a - bi) (a - bi)
  101. // -------- = -------- -------- = -----------
  102. // (a + bi) (a + bi) (a - bi) (a^2 + b^2)
  103. //
  104. // Letting c = 1/(a^2 + b^2), this is
  105. //
  106. // 1/(a+bi) = a*c - b*ci.
  107. var asq_plus_bsq PrimeFieldElement
  108. var asq, bsq fp751X2
  109. fp751Mul(&asq, a, a) // = a*a*R*R
  110. fp751Mul(&bsq, b, b) // = b*b*R*R
  111. fp751X2AddLazy(&asq, &asq, &bsq) // = (a^2 + b^2)*R*R
  112. fp751MontgomeryReduce(&asq_plus_bsq.A, &asq) // = (a^2 + b^2)*R mod p
  113. // Now asq_plus_bsq = a^2 + b^2
  114. // Invert asq_plus_bsq
  115. inv := asq_plus_bsq
  116. inv.Mul(&asq_plus_bsq, &asq_plus_bsq)
  117. inv.P34(&inv)
  118. inv.Mul(&inv, &inv)
  119. inv.Mul(&inv, &asq_plus_bsq)
  120. var ac fp751X2
  121. fp751Mul(&ac, a, &inv.A)
  122. fp751MontgomeryReduce(&dest.A, &ac)
  123. var minus_b Fp751Element
  124. fp751SubReduced(&minus_b, &minus_b, b)
  125. var minus_bc fp751X2
  126. fp751Mul(&minus_bc, &minus_b, &inv.A)
  127. fp751MontgomeryReduce(&dest.B, &minus_bc)
  128. return dest
  129. }
  130. // Set (y1, y2, y3) = (1/x1, 1/x2, 1/x3).
  131. //
  132. // All xi, yi must be distinct.
  133. func ExtensionFieldBatch3Inv(x1, x2, x3, y1, y2, y3 *ExtensionFieldElement) {
  134. var x1x2, t ExtensionFieldElement
  135. x1x2.Mul(x1, x2) // x1*x2
  136. t.Mul(&x1x2, x3).Inv(&t) // 1/(x1*x2*x3)
  137. y1.Mul(&t, x2).Mul(y1, x3) // 1/x1
  138. y2.Mul(&t, x1).Mul(y2, x3) // 1/x2
  139. y3.Mul(&t, &x1x2) // 1/x3
  140. }
  141. // Set dest = x * x
  142. //
  143. // Allowed to overlap dest with x.
  144. //
  145. // Returns dest to allow chaining operations.
  146. func (dest *ExtensionFieldElement) Square(x *ExtensionFieldElement) *ExtensionFieldElement {
  147. a := &x.A
  148. b := &x.B
  149. // We want to compute
  150. //
  151. // (a + bi)*(a + bi) = (a^2 - b^2) + 2abi.
  152. var a2, a_plus_b, a_minus_b Fp751Element
  153. fp751AddReduced(&a2, a, a) // = a*R + a*R = 2*a*R
  154. fp751AddReduced(&a_plus_b, a, b) // = a*R + b*R = (a+b)*R
  155. fp751SubReduced(&a_minus_b, a, b) // = a*R - b*R = (a-b)*R
  156. var asq_minus_bsq, ab2 fp751X2
  157. fp751Mul(&asq_minus_bsq, &a_plus_b, &a_minus_b) // = (a+b)*(a-b)*R*R = (a^2 - b^2)*R*R
  158. fp751Mul(&ab2, &a2, b) // = 2*a*b*R*R
  159. fp751MontgomeryReduce(&dest.A, &asq_minus_bsq) // = (a^2 - b^2)*R mod p
  160. fp751MontgomeryReduce(&dest.B, &ab2) // = 2*a*b*R mod p
  161. return dest
  162. }
  163. // Set dest = lhs + rhs.
  164. //
  165. // Allowed to overlap lhs or rhs with dest.
  166. //
  167. // Returns dest to allow chaining operations.
  168. func (dest *ExtensionFieldElement) Add(lhs, rhs *ExtensionFieldElement) *ExtensionFieldElement {
  169. fp751AddReduced(&dest.A, &lhs.A, &rhs.A)
  170. fp751AddReduced(&dest.B, &lhs.B, &rhs.B)
  171. return dest
  172. }
  173. // Set dest = lhs - rhs.
  174. //
  175. // Allowed to overlap lhs or rhs with dest.
  176. //
  177. // Returns dest to allow chaining operations.
  178. func (dest *ExtensionFieldElement) Sub(lhs, rhs *ExtensionFieldElement) *ExtensionFieldElement {
  179. fp751SubReduced(&dest.A, &lhs.A, &rhs.A)
  180. fp751SubReduced(&dest.B, &lhs.B, &rhs.B)
  181. return dest
  182. }
  183. // If choice = 1u8, set (x,y) = (y,x). If choice = 0u8, set (x,y) = (x,y).
  184. //
  185. // Returns dest to allow chaining operations.
  186. func ExtensionFieldConditionalSwap(x, y *ExtensionFieldElement, choice uint8) {
  187. fp751ConditionalSwap(&x.A, &y.A, choice)
  188. fp751ConditionalSwap(&x.B, &y.B, choice)
  189. }
  190. // Returns true if lhs = rhs. Takes variable time.
  191. func (lhs *ExtensionFieldElement) VartimeEq(rhs *ExtensionFieldElement) bool {
  192. return lhs.A.vartimeEq(rhs.A) && lhs.B.vartimeEq(rhs.B)
  193. }
  194. // Convert the input to wire format.
  195. //
  196. // The output byte slice must be at least 188 bytes long.
  197. func (x *ExtensionFieldElement) ToBytes(output []byte) {
  198. if len(output) < 188 {
  199. panic("output byte slice too short, need 188 bytes")
  200. }
  201. var a,b Fp751Element
  202. var aR fp751X2
  203. // convert from montgomery domain
  204. copy(aR[:], x.A[:]) // = a*R
  205. fp751MontgomeryReduce(&a, &aR) // = a mod p in [0, 2p)
  206. fp751StrongReduce(&a) // = a mod p in [0, p)
  207. copy(aR[:], x.B[:])
  208. fp751MontgomeryReduce(&b, &aR)
  209. fp751StrongReduce(&b)
  210. // convert to bytes in little endian form. 8*12 = 96, but we drop the last two bytes
  211. // since p is 751 < 752=94*8 bits.
  212. for i := 0; i < 94; i++ {
  213. // set i = j*8 + k
  214. j := i / 8
  215. k := uint64(i % 8)
  216. output[i] = byte(a[j] >> (8 * k))
  217. output[i+94] = byte(b[j] >> (8 * k))
  218. }
  219. }
  220. // Read 188 bytes into the given ExtensionFieldElement.
  221. //
  222. // It is an error to call this function if the input byte slice is less than 188 bytes long.
  223. func (x *ExtensionFieldElement) FromBytes(input []byte) {
  224. if len(input) < 188 {
  225. panic("input byte slice too short, need 188 bytes")
  226. }
  227. for i:=0; i<94; i++ {
  228. j := i / 8
  229. k := uint64(i % 8)
  230. x.A[j] |= uint64(input[i]) << (8 * k)
  231. x.B[j] |= uint64(input[i+94]) << (8 * k)
  232. }
  233. // convert to montgomery domain
  234. var aRR fp751X2
  235. fp751Mul(&aRR, &x.A, &montgomeryRsq) // = a*R*R
  236. fp751MontgomeryReduce(&x.A, &aRR) // = a*R mod p
  237. fp751Mul(&aRR, &x.B, &montgomeryRsq) // = a*R*R
  238. fp751MontgomeryReduce(&x.B, &aRR) // = a*R mod p
  239. }
  240. //------------------------------------------------------------------------------
  241. // Prime Field
  242. //------------------------------------------------------------------------------
  243. // Represents an element of the prime field F_p.
  244. type PrimeFieldElement struct {
  245. // This field element is in Montgomery form, so that the value `A` is
  246. // represented by `aR mod p`.
  247. A Fp751Element
  248. }
  249. var zeroPrimeField = PrimeFieldElement{
  250. A: Fp751Element{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
  251. }
  252. var onePrimeField = PrimeFieldElement{
  253. A: Fp751Element{0x249ad, 0x0, 0x0, 0x0, 0x0, 0x8310000000000000, 0x5527b1e4375c6c66, 0x697797bf3f4f24d0, 0xc89db7b2ac5c4e2e, 0x4ca4b439d2076956, 0x10f7926c7512c7e9, 0x2d5b24bce5e2},
  254. }
  255. // Set dest = lhs * rhs.
  256. //
  257. // Allowed to overlap lhs or rhs with dest.
  258. //
  259. // Returns dest to allow chaining operations.
  260. func (dest *PrimeFieldElement) Mul(lhs, rhs *PrimeFieldElement) *PrimeFieldElement {
  261. a := &lhs.A // = a*R
  262. b := &rhs.A // = b*R
  263. var ab fp751X2
  264. fp751Mul(&ab, a, b) // = a*b*R*R
  265. fp751MontgomeryReduce(&dest.A, &ab) // = a*b*R mod p
  266. return dest
  267. }
  268. // Set dest = x^(2^k), for k >= 1, by repeated squarings.
  269. //
  270. // Allowed to overlap x with dest.
  271. //
  272. // Returns dest to allow chaining operations.
  273. func (dest *PrimeFieldElement) Pow2k(x *PrimeFieldElement, k uint8) *PrimeFieldElement {
  274. dest.Mul(x, x)
  275. for i := uint8(1); i < k; i++ {
  276. dest.Mul(dest, dest)
  277. }
  278. return dest
  279. }
  280. // Set dest = x^((p-3)/4). If x is square, this is 1/sqrt(x).
  281. //
  282. // Allowed to overlap x with dest.
  283. //
  284. // Returns dest to allow chaining operations.
  285. func (dest *PrimeFieldElement) P34(x *PrimeFieldElement) *PrimeFieldElement {
  286. // Sliding-window strategy computed with Sage, awk, sed, and tr.
  287. //
  288. // This performs sum(powStrategy) = 744 squarings and len(mulStrategy)
  289. // = 137 multiplications, in addition to 1 squaring and 15
  290. // multiplications to build a lookup table.
  291. //
  292. // In total this is 745 squarings, 152 multiplications. Since squaring
  293. // is not implemented for the prime field, this is 897 multiplications
  294. // in total.
  295. 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}
  296. 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}
  297. initialMul := uint8(27)
  298. // Build a lookup table of odd multiples of x.
  299. lookup := [16]PrimeFieldElement{}
  300. xx := &PrimeFieldElement{}
  301. xx.Mul(x, x) // Set xx = x^2
  302. lookup[0] = *x
  303. for i := 1; i < 16; i++ {
  304. lookup[i].Mul(&lookup[i-1], xx)
  305. }
  306. // Now lookup = {x, x^3, x^5, ... }
  307. // so that lookup[i] = x^{2*i + 1}
  308. // so that lookup[k/2] = x^k, for odd k
  309. *dest = lookup[initialMul/2]
  310. for i := uint8(0); i < 137; i++ {
  311. dest.Pow2k(dest, powStrategy[i])
  312. dest.Mul(dest, &lookup[mulStrategy[i]/2])
  313. }
  314. return dest
  315. }
  316. //------------------------------------------------------------------------------
  317. // Internals
  318. //------------------------------------------------------------------------------
  319. const fp751NumWords = 12
  320. // (2^768)^2 mod p
  321. // This can't be a constant because Go doesn't allow array constants, so try
  322. // not to modify it.
  323. var montgomeryRsq = Fp751Element{2535603850726686808, 15780896088201250090, 6788776303855402382, 17585428585582356230, 5274503137951975249, 2266259624764636289, 11695651972693921304, 13072885652150159301, 4908312795585420432, 6229583484603254826, 488927695601805643, 72213483953973}
  324. // Internal representation of an element of the base field F_p.
  325. //
  326. // This type is distinct from PrimeFieldElement in that no particular meaning
  327. // is assigned to the representation -- it could represent an element in
  328. // Montgomery form, or not. Tracking the meaning of the field element is left
  329. // to higher types.
  330. type Fp751Element [fp751NumWords]uint64
  331. // Represents an intermediate product of two elements of the base field F_p.
  332. type fp751X2 [2 * fp751NumWords]uint64
  333. func (x Fp751Element) vartimeEq(y Fp751Element) bool {
  334. fp751StrongReduce(&x)
  335. fp751StrongReduce(&y)
  336. eq := true
  337. for i := 0; i < fp751NumWords; i++ {
  338. eq = (x[i] == y[i]) && eq
  339. }
  340. return eq
  341. }