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.

249 lines
5.2 KiB

  1. // Copyright 2012 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package bn256
  5. import (
  6. "math/big"
  7. )
  8. // twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are
  9. // kept in Jacobian form and t=z² when valid. The group G₂ is the set of
  10. // n-torsion points of this curve over GF(p²) (where n = Order)
  11. type twistPoint struct {
  12. x, y, z, t *gfP2
  13. }
  14. var twistB = &gfP2{
  15. bigFromBase10("6500054969564660373279643874235990574282535810762300357187714502686418407178"),
  16. bigFromBase10("45500384786952622612957507119651934019977750675336102500314001518804928850249"),
  17. }
  18. // twistGen is the generator of group G₂.
  19. var twistGen = &twistPoint{
  20. &gfP2{
  21. bigFromBase10("21167961636542580255011770066570541300993051739349375019639421053990175267184"),
  22. bigFromBase10("64746500191241794695844075326670126197795977525365406531717464316923369116492"),
  23. },
  24. &gfP2{
  25. bigFromBase10("20666913350058776956210519119118544732556678129809273996262322366050359951122"),
  26. bigFromBase10("17778617556404439934652658462602675281523610326338642107814333856843981424549"),
  27. },
  28. &gfP2{
  29. bigFromBase10("0"),
  30. bigFromBase10("1"),
  31. },
  32. &gfP2{
  33. bigFromBase10("0"),
  34. bigFromBase10("1"),
  35. },
  36. }
  37. func newTwistPoint(pool *bnPool) *twistPoint {
  38. return &twistPoint{
  39. newGFp2(pool),
  40. newGFp2(pool),
  41. newGFp2(pool),
  42. newGFp2(pool),
  43. }
  44. }
  45. func (c *twistPoint) String() string {
  46. return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")"
  47. }
  48. func (c *twistPoint) Put(pool *bnPool) {
  49. c.x.Put(pool)
  50. c.y.Put(pool)
  51. c.z.Put(pool)
  52. c.t.Put(pool)
  53. }
  54. func (c *twistPoint) Set(a *twistPoint) {
  55. c.x.Set(a.x)
  56. c.y.Set(a.y)
  57. c.z.Set(a.z)
  58. c.t.Set(a.t)
  59. }
  60. // IsOnCurve returns true iff c is on the curve where c must be in affine form.
  61. func (c *twistPoint) IsOnCurve() bool {
  62. pool := new(bnPool)
  63. yy := newGFp2(pool).Square(c.y, pool)
  64. xxx := newGFp2(pool).Square(c.x, pool)
  65. xxx.Mul(xxx, c.x, pool)
  66. yy.Sub(yy, xxx)
  67. yy.Sub(yy, twistB)
  68. yy.Minimal()
  69. return yy.x.Sign() == 0 && yy.y.Sign() == 0
  70. }
  71. func (c *twistPoint) SetInfinity() {
  72. c.z.SetZero()
  73. }
  74. func (c *twistPoint) IsInfinity() bool {
  75. return c.z.IsZero()
  76. }
  77. func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) {
  78. // For additional comments, see the same function in curve.go.
  79. if a.IsInfinity() {
  80. c.Set(b)
  81. return
  82. }
  83. if b.IsInfinity() {
  84. c.Set(a)
  85. return
  86. }
  87. // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
  88. z1z1 := newGFp2(pool).Square(a.z, pool)
  89. z2z2 := newGFp2(pool).Square(b.z, pool)
  90. u1 := newGFp2(pool).Mul(a.x, z2z2, pool)
  91. u2 := newGFp2(pool).Mul(b.x, z1z1, pool)
  92. t := newGFp2(pool).Mul(b.z, z2z2, pool)
  93. s1 := newGFp2(pool).Mul(a.y, t, pool)
  94. t.Mul(a.z, z1z1, pool)
  95. s2 := newGFp2(pool).Mul(b.y, t, pool)
  96. h := newGFp2(pool).Sub(u2, u1)
  97. xEqual := h.IsZero()
  98. t.Add(h, h)
  99. i := newGFp2(pool).Square(t, pool)
  100. j := newGFp2(pool).Mul(h, i, pool)
  101. t.Sub(s2, s1)
  102. yEqual := t.IsZero()
  103. if xEqual && yEqual {
  104. c.Double(a, pool)
  105. return
  106. }
  107. r := newGFp2(pool).Add(t, t)
  108. v := newGFp2(pool).Mul(u1, i, pool)
  109. t4 := newGFp2(pool).Square(r, pool)
  110. t.Add(v, v)
  111. t6 := newGFp2(pool).Sub(t4, j)
  112. c.x.Sub(t6, t)
  113. t.Sub(v, c.x) // t7
  114. t4.Mul(s1, j, pool) // t8
  115. t6.Add(t4, t4) // t9
  116. t4.Mul(r, t, pool) // t10
  117. c.y.Sub(t4, t6)
  118. t.Add(a.z, b.z) // t11
  119. t4.Square(t, pool) // t12
  120. t.Sub(t4, z1z1) // t13
  121. t4.Sub(t, z2z2) // t14
  122. c.z.Mul(t4, h, pool)
  123. z1z1.Put(pool)
  124. z2z2.Put(pool)
  125. u1.Put(pool)
  126. u2.Put(pool)
  127. t.Put(pool)
  128. s1.Put(pool)
  129. s2.Put(pool)
  130. h.Put(pool)
  131. i.Put(pool)
  132. j.Put(pool)
  133. r.Put(pool)
  134. v.Put(pool)
  135. t4.Put(pool)
  136. t6.Put(pool)
  137. }
  138. func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
  139. // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
  140. A := newGFp2(pool).Square(a.x, pool)
  141. B := newGFp2(pool).Square(a.y, pool)
  142. C := newGFp2(pool).Square(B, pool)
  143. t := newGFp2(pool).Add(a.x, B)
  144. t2 := newGFp2(pool).Square(t, pool)
  145. t.Sub(t2, A)
  146. t2.Sub(t, C)
  147. d := newGFp2(pool).Add(t2, t2)
  148. t.Add(A, A)
  149. e := newGFp2(pool).Add(t, A)
  150. f := newGFp2(pool).Square(e, pool)
  151. t.Add(d, d)
  152. c.x.Sub(f, t)
  153. t.Add(C, C)
  154. t2.Add(t, t)
  155. t.Add(t2, t2)
  156. c.y.Sub(d, c.x)
  157. t2.Mul(e, c.y, pool)
  158. c.y.Sub(t2, t)
  159. t.Mul(a.y, a.z, pool)
  160. c.z.Add(t, t)
  161. A.Put(pool)
  162. B.Put(pool)
  163. C.Put(pool)
  164. t.Put(pool)
  165. t2.Put(pool)
  166. d.Put(pool)
  167. e.Put(pool)
  168. f.Put(pool)
  169. }
  170. func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint {
  171. sum := newTwistPoint(pool)
  172. sum.SetInfinity()
  173. t := newTwistPoint(pool)
  174. for i := scalar.BitLen(); i >= 0; i-- {
  175. t.Double(sum, pool)
  176. if scalar.Bit(i) != 0 {
  177. sum.Add(t, a, pool)
  178. } else {
  179. sum.Set(t)
  180. }
  181. }
  182. c.Set(sum)
  183. sum.Put(pool)
  184. t.Put(pool)
  185. return c
  186. }
  187. func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint {
  188. if c.z.IsOne() {
  189. return c
  190. }
  191. zInv := newGFp2(pool).Invert(c.z, pool)
  192. t := newGFp2(pool).Mul(c.y, zInv, pool)
  193. zInv2 := newGFp2(pool).Square(zInv, pool)
  194. c.y.Mul(t, zInv2, pool)
  195. t.Mul(c.x, zInv2, pool)
  196. c.x.Set(t)
  197. c.z.SetOne()
  198. c.t.SetOne()
  199. zInv.Put(pool)
  200. t.Put(pool)
  201. zInv2.Put(pool)
  202. return c
  203. }
  204. func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) {
  205. c.x.Set(a.x)
  206. c.y.SetZero()
  207. c.y.Sub(c.y, a.y)
  208. c.z.Set(a.z)
  209. c.t.SetZero()
  210. }