twist.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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("266929791119991161246907387137283842545076965332900288569378510910307636690"),
  16. bigFromBase10("19485874751759354771024239261021720505790618469301721065564631296452457478373"),
  17. }
  18. // twistGen is the generator of group G₂.
  19. var twistGen = &twistPoint{
  20. &gfP2{
  21. bigFromBase10("11559732032986387107991004021392285783925812861821192530917403151452391805634"),
  22. bigFromBase10("10857046999023057135944570762232829481370756359578518086990519993285655852781"),
  23. },
  24. &gfP2{
  25. bigFromBase10("4082367875863433681332203403145435568316851327593401208105741076214120093531"),
  26. bigFromBase10("8495653923123431417604973247489272438418190587263600148770280649306958101930"),
  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. if yy.x.Sign() != 0 || yy.y.Sign() != 0 {
  70. return false
  71. }
  72. cneg := newTwistPoint(pool)
  73. cneg.Mul(c, Order, pool)
  74. return cneg.z.IsZero()
  75. }
  76. func (c *twistPoint) SetInfinity() {
  77. c.z.SetZero()
  78. }
  79. func (c *twistPoint) IsInfinity() bool {
  80. return c.z.IsZero()
  81. }
  82. func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) {
  83. // For additional comments, see the same function in curve.go.
  84. if a.IsInfinity() {
  85. c.Set(b)
  86. return
  87. }
  88. if b.IsInfinity() {
  89. c.Set(a)
  90. return
  91. }
  92. // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
  93. z1z1 := newGFp2(pool).Square(a.z, pool)
  94. z2z2 := newGFp2(pool).Square(b.z, pool)
  95. u1 := newGFp2(pool).Mul(a.x, z2z2, pool)
  96. u2 := newGFp2(pool).Mul(b.x, z1z1, pool)
  97. t := newGFp2(pool).Mul(b.z, z2z2, pool)
  98. s1 := newGFp2(pool).Mul(a.y, t, pool)
  99. t.Mul(a.z, z1z1, pool)
  100. s2 := newGFp2(pool).Mul(b.y, t, pool)
  101. h := newGFp2(pool).Sub(u2, u1)
  102. xEqual := h.IsZero()
  103. t.Add(h, h)
  104. i := newGFp2(pool).Square(t, pool)
  105. j := newGFp2(pool).Mul(h, i, pool)
  106. t.Sub(s2, s1)
  107. yEqual := t.IsZero()
  108. if xEqual && yEqual {
  109. c.Double(a, pool)
  110. return
  111. }
  112. r := newGFp2(pool).Add(t, t)
  113. v := newGFp2(pool).Mul(u1, i, pool)
  114. t4 := newGFp2(pool).Square(r, pool)
  115. t.Add(v, v)
  116. t6 := newGFp2(pool).Sub(t4, j)
  117. c.x.Sub(t6, t)
  118. t.Sub(v, c.x) // t7
  119. t4.Mul(s1, j, pool) // t8
  120. t6.Add(t4, t4) // t9
  121. t4.Mul(r, t, pool) // t10
  122. c.y.Sub(t4, t6)
  123. t.Add(a.z, b.z) // t11
  124. t4.Square(t, pool) // t12
  125. t.Sub(t4, z1z1) // t13
  126. t4.Sub(t, z2z2) // t14
  127. c.z.Mul(t4, h, pool)
  128. z1z1.Put(pool)
  129. z2z2.Put(pool)
  130. u1.Put(pool)
  131. u2.Put(pool)
  132. t.Put(pool)
  133. s1.Put(pool)
  134. s2.Put(pool)
  135. h.Put(pool)
  136. i.Put(pool)
  137. j.Put(pool)
  138. r.Put(pool)
  139. v.Put(pool)
  140. t4.Put(pool)
  141. t6.Put(pool)
  142. }
  143. func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
  144. // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
  145. A := newGFp2(pool).Square(a.x, pool)
  146. B := newGFp2(pool).Square(a.y, pool)
  147. C_ := newGFp2(pool).Square(B, pool)
  148. t := newGFp2(pool).Add(a.x, B)
  149. t2 := newGFp2(pool).Square(t, pool)
  150. t.Sub(t2, A)
  151. t2.Sub(t, C_)
  152. d := newGFp2(pool).Add(t2, t2)
  153. t.Add(A, A)
  154. e := newGFp2(pool).Add(t, A)
  155. f := newGFp2(pool).Square(e, pool)
  156. t.Add(d, d)
  157. c.x.Sub(f, t)
  158. t.Add(C_, C_)
  159. t2.Add(t, t)
  160. t.Add(t2, t2)
  161. c.y.Sub(d, c.x)
  162. t2.Mul(e, c.y, pool)
  163. c.y.Sub(t2, t)
  164. t.Mul(a.y, a.z, pool)
  165. c.z.Add(t, t)
  166. A.Put(pool)
  167. B.Put(pool)
  168. C_.Put(pool)
  169. t.Put(pool)
  170. t2.Put(pool)
  171. d.Put(pool)
  172. e.Put(pool)
  173. f.Put(pool)
  174. }
  175. func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint {
  176. sum := newTwistPoint(pool)
  177. sum.SetInfinity()
  178. t := newTwistPoint(pool)
  179. for i := scalar.BitLen(); i >= 0; i-- {
  180. t.Double(sum, pool)
  181. if scalar.Bit(i) != 0 {
  182. sum.Add(t, a, pool)
  183. } else {
  184. sum.Set(t)
  185. }
  186. }
  187. c.Set(sum)
  188. sum.Put(pool)
  189. t.Put(pool)
  190. return c
  191. }
  192. // MakeAffine converts c to affine form and returns c. If c is ∞, then it sets
  193. // c to 0 : 1 : 0.
  194. func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint {
  195. if c.z.IsOne() {
  196. return c
  197. }
  198. if c.IsInfinity() {
  199. c.x.SetZero()
  200. c.y.SetOne()
  201. c.z.SetZero()
  202. c.t.SetZero()
  203. return c
  204. }
  205. zInv := newGFp2(pool).Invert(c.z, pool)
  206. t := newGFp2(pool).Mul(c.y, zInv, pool)
  207. zInv2 := newGFp2(pool).Square(zInv, pool)
  208. c.y.Mul(t, zInv2, pool)
  209. t.Mul(c.x, zInv2, pool)
  210. c.x.Set(t)
  211. c.z.SetOne()
  212. c.t.SetOne()
  213. zInv.Put(pool)
  214. t.Put(pool)
  215. zInv2.Put(pool)
  216. return c
  217. }
  218. func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) {
  219. c.x.Set(a.x)
  220. c.y.SetZero()
  221. c.y.Sub(c.y, a.y)
  222. c.z.Set(a.z)
  223. c.t.SetZero()
  224. }