edwards25519.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. // Copyright (c) 2017 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 edwards25519
  5. import (
  6. "errors"
  7. "filippo.io/edwards25519/field"
  8. )
  9. // Point types.
  10. type projP1xP1 struct {
  11. X, Y, Z, T field.Element
  12. }
  13. type projP2 struct {
  14. X, Y, Z field.Element
  15. }
  16. // Point represents a point on the edwards25519 curve.
  17. //
  18. // This type works similarly to math/big.Int, and all arguments and receivers
  19. // are allowed to alias.
  20. //
  21. // The zero value is NOT valid, and it may be used only as a receiver.
  22. type Point struct {
  23. // Make the type not comparable (i.e. used with == or as a map key), as
  24. // equivalent points can be represented by different Go values.
  25. _ incomparable
  26. // The point is internally represented in extended coordinates (X, Y, Z, T)
  27. // where x = X/Z, y = Y/Z, and xy = T/Z per https://eprint.iacr.org/2008/522.
  28. x, y, z, t field.Element
  29. }
  30. type incomparable [0]func()
  31. func checkInitialized(points ...*Point) {
  32. for _, p := range points {
  33. if p.x == (field.Element{}) && p.y == (field.Element{}) {
  34. panic("edwards25519: use of uninitialized Point")
  35. }
  36. }
  37. }
  38. type projCached struct {
  39. YplusX, YminusX, Z, T2d field.Element
  40. }
  41. type affineCached struct {
  42. YplusX, YminusX, T2d field.Element
  43. }
  44. // Constructors.
  45. func (v *projP2) Zero() *projP2 {
  46. v.X.Zero()
  47. v.Y.One()
  48. v.Z.One()
  49. return v
  50. }
  51. // identity is the point at infinity.
  52. var identity, _ = new(Point).SetBytes([]byte{
  53. 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  54. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
  55. // NewIdentityPoint returns a new Point set to the identity.
  56. func NewIdentityPoint() *Point {
  57. return new(Point).Set(identity)
  58. }
  59. // generator is the canonical curve basepoint. See TestGenerator for the
  60. // correspondence of this encoding with the values in RFC 8032.
  61. var generator, _ = new(Point).SetBytes([]byte{
  62. 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
  63. 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
  64. 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
  65. 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66})
  66. // NewGeneratorPoint returns a new Point set to the canonical generator.
  67. func NewGeneratorPoint() *Point {
  68. return new(Point).Set(generator)
  69. }
  70. func (v *projCached) Zero() *projCached {
  71. v.YplusX.One()
  72. v.YminusX.One()
  73. v.Z.One()
  74. v.T2d.Zero()
  75. return v
  76. }
  77. func (v *affineCached) Zero() *affineCached {
  78. v.YplusX.One()
  79. v.YminusX.One()
  80. v.T2d.Zero()
  81. return v
  82. }
  83. // Assignments.
  84. // Set sets v = u, and returns v.
  85. func (v *Point) Set(u *Point) *Point {
  86. *v = *u
  87. return v
  88. }
  89. // Encoding.
  90. // Bytes returns the canonical 32-byte encoding of v, according to RFC 8032,
  91. // Section 5.1.2.
  92. func (v *Point) Bytes() []byte {
  93. // This function is outlined to make the allocations inline in the caller
  94. // rather than happen on the heap.
  95. var buf [32]byte
  96. return v.bytes(&buf)
  97. }
  98. func (v *Point) bytes(buf *[32]byte) []byte {
  99. checkInitialized(v)
  100. var zInv, x, y field.Element
  101. zInv.Invert(&v.z) // zInv = 1 / Z
  102. x.Multiply(&v.x, &zInv) // x = X / Z
  103. y.Multiply(&v.y, &zInv) // y = Y / Z
  104. out := copyFieldElement(buf, &y)
  105. out[31] |= byte(x.IsNegative() << 7)
  106. return out
  107. }
  108. var feOne = new(field.Element).One()
  109. // SetBytes sets v = x, where x is a 32-byte encoding of v. If x does not
  110. // represent a valid point on the curve, SetBytes returns nil and an error and
  111. // the receiver is unchanged. Otherwise, SetBytes returns v.
  112. //
  113. // Note that SetBytes accepts all non-canonical encodings of valid points.
  114. // That is, it follows decoding rules that match most implementations in
  115. // the ecosystem rather than RFC 8032.
  116. func (v *Point) SetBytes(x []byte) (*Point, error) {
  117. // Specifically, the non-canonical encodings that are accepted are
  118. // 1) the ones where the field element is not reduced (see the
  119. // (*field.Element).SetBytes docs) and
  120. // 2) the ones where the x-coordinate is zero and the sign bit is set.
  121. //
  122. // Read more at https://hdevalence.ca/blog/2020-10-04-its-25519am,
  123. // specifically the "Canonical A, R" section.
  124. y, err := new(field.Element).SetBytes(x)
  125. if err != nil {
  126. return nil, errors.New("edwards25519: invalid point encoding length")
  127. }
  128. // -x² + y² = 1 + dx²y²
  129. // x² + dx²y² = x²(dy² + 1) = y² - 1
  130. // x² = (y² - 1) / (dy² + 1)
  131. // u = y² - 1
  132. y2 := new(field.Element).Square(y)
  133. u := new(field.Element).Subtract(y2, feOne)
  134. // v = dy² + 1
  135. vv := new(field.Element).Multiply(y2, d)
  136. vv = vv.Add(vv, feOne)
  137. // x = +√(u/v)
  138. xx, wasSquare := new(field.Element).SqrtRatio(u, vv)
  139. if wasSquare == 0 {
  140. return nil, errors.New("edwards25519: invalid point encoding")
  141. }
  142. // Select the negative square root if the sign bit is set.
  143. xxNeg := new(field.Element).Negate(xx)
  144. xx = xx.Select(xxNeg, xx, int(x[31]>>7))
  145. v.x.Set(xx)
  146. v.y.Set(y)
  147. v.z.One()
  148. v.t.Multiply(xx, y) // xy = T / Z
  149. return v, nil
  150. }
  151. func copyFieldElement(buf *[32]byte, v *field.Element) []byte {
  152. copy(buf[:], v.Bytes())
  153. return buf[:]
  154. }
  155. // Conversions.
  156. func (v *projP2) FromP1xP1(p *projP1xP1) *projP2 {
  157. v.X.Multiply(&p.X, &p.T)
  158. v.Y.Multiply(&p.Y, &p.Z)
  159. v.Z.Multiply(&p.Z, &p.T)
  160. return v
  161. }
  162. func (v *projP2) FromP3(p *Point) *projP2 {
  163. v.X.Set(&p.x)
  164. v.Y.Set(&p.y)
  165. v.Z.Set(&p.z)
  166. return v
  167. }
  168. func (v *Point) fromP1xP1(p *projP1xP1) *Point {
  169. v.x.Multiply(&p.X, &p.T)
  170. v.y.Multiply(&p.Y, &p.Z)
  171. v.z.Multiply(&p.Z, &p.T)
  172. v.t.Multiply(&p.X, &p.Y)
  173. return v
  174. }
  175. func (v *Point) fromP2(p *projP2) *Point {
  176. v.x.Multiply(&p.X, &p.Z)
  177. v.y.Multiply(&p.Y, &p.Z)
  178. v.z.Square(&p.Z)
  179. v.t.Multiply(&p.X, &p.Y)
  180. return v
  181. }
  182. // d is a constant in the curve equation.
  183. var d, _ = new(field.Element).SetBytes([]byte{
  184. 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
  185. 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
  186. 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
  187. 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52})
  188. var d2 = new(field.Element).Add(d, d)
  189. func (v *projCached) FromP3(p *Point) *projCached {
  190. v.YplusX.Add(&p.y, &p.x)
  191. v.YminusX.Subtract(&p.y, &p.x)
  192. v.Z.Set(&p.z)
  193. v.T2d.Multiply(&p.t, d2)
  194. return v
  195. }
  196. func (v *affineCached) FromP3(p *Point) *affineCached {
  197. v.YplusX.Add(&p.y, &p.x)
  198. v.YminusX.Subtract(&p.y, &p.x)
  199. v.T2d.Multiply(&p.t, d2)
  200. var invZ field.Element
  201. invZ.Invert(&p.z)
  202. v.YplusX.Multiply(&v.YplusX, &invZ)
  203. v.YminusX.Multiply(&v.YminusX, &invZ)
  204. v.T2d.Multiply(&v.T2d, &invZ)
  205. return v
  206. }
  207. // (Re)addition and subtraction.
  208. // Add sets v = p + q, and returns v.
  209. func (v *Point) Add(p, q *Point) *Point {
  210. checkInitialized(p, q)
  211. qCached := new(projCached).FromP3(q)
  212. result := new(projP1xP1).Add(p, qCached)
  213. return v.fromP1xP1(result)
  214. }
  215. // Subtract sets v = p - q, and returns v.
  216. func (v *Point) Subtract(p, q *Point) *Point {
  217. checkInitialized(p, q)
  218. qCached := new(projCached).FromP3(q)
  219. result := new(projP1xP1).Sub(p, qCached)
  220. return v.fromP1xP1(result)
  221. }
  222. func (v *projP1xP1) Add(p *Point, q *projCached) *projP1xP1 {
  223. var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element
  224. YplusX.Add(&p.y, &p.x)
  225. YminusX.Subtract(&p.y, &p.x)
  226. PP.Multiply(&YplusX, &q.YplusX)
  227. MM.Multiply(&YminusX, &q.YminusX)
  228. TT2d.Multiply(&p.t, &q.T2d)
  229. ZZ2.Multiply(&p.z, &q.Z)
  230. ZZ2.Add(&ZZ2, &ZZ2)
  231. v.X.Subtract(&PP, &MM)
  232. v.Y.Add(&PP, &MM)
  233. v.Z.Add(&ZZ2, &TT2d)
  234. v.T.Subtract(&ZZ2, &TT2d)
  235. return v
  236. }
  237. func (v *projP1xP1) Sub(p *Point, q *projCached) *projP1xP1 {
  238. var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element
  239. YplusX.Add(&p.y, &p.x)
  240. YminusX.Subtract(&p.y, &p.x)
  241. PP.Multiply(&YplusX, &q.YminusX) // flipped sign
  242. MM.Multiply(&YminusX, &q.YplusX) // flipped sign
  243. TT2d.Multiply(&p.t, &q.T2d)
  244. ZZ2.Multiply(&p.z, &q.Z)
  245. ZZ2.Add(&ZZ2, &ZZ2)
  246. v.X.Subtract(&PP, &MM)
  247. v.Y.Add(&PP, &MM)
  248. v.Z.Subtract(&ZZ2, &TT2d) // flipped sign
  249. v.T.Add(&ZZ2, &TT2d) // flipped sign
  250. return v
  251. }
  252. func (v *projP1xP1) AddAffine(p *Point, q *affineCached) *projP1xP1 {
  253. var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element
  254. YplusX.Add(&p.y, &p.x)
  255. YminusX.Subtract(&p.y, &p.x)
  256. PP.Multiply(&YplusX, &q.YplusX)
  257. MM.Multiply(&YminusX, &q.YminusX)
  258. TT2d.Multiply(&p.t, &q.T2d)
  259. Z2.Add(&p.z, &p.z)
  260. v.X.Subtract(&PP, &MM)
  261. v.Y.Add(&PP, &MM)
  262. v.Z.Add(&Z2, &TT2d)
  263. v.T.Subtract(&Z2, &TT2d)
  264. return v
  265. }
  266. func (v *projP1xP1) SubAffine(p *Point, q *affineCached) *projP1xP1 {
  267. var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element
  268. YplusX.Add(&p.y, &p.x)
  269. YminusX.Subtract(&p.y, &p.x)
  270. PP.Multiply(&YplusX, &q.YminusX) // flipped sign
  271. MM.Multiply(&YminusX, &q.YplusX) // flipped sign
  272. TT2d.Multiply(&p.t, &q.T2d)
  273. Z2.Add(&p.z, &p.z)
  274. v.X.Subtract(&PP, &MM)
  275. v.Y.Add(&PP, &MM)
  276. v.Z.Subtract(&Z2, &TT2d) // flipped sign
  277. v.T.Add(&Z2, &TT2d) // flipped sign
  278. return v
  279. }
  280. // Doubling.
  281. func (v *projP1xP1) Double(p *projP2) *projP1xP1 {
  282. var XX, YY, ZZ2, XplusYsq field.Element
  283. XX.Square(&p.X)
  284. YY.Square(&p.Y)
  285. ZZ2.Square(&p.Z)
  286. ZZ2.Add(&ZZ2, &ZZ2)
  287. XplusYsq.Add(&p.X, &p.Y)
  288. XplusYsq.Square(&XplusYsq)
  289. v.Y.Add(&YY, &XX)
  290. v.Z.Subtract(&YY, &XX)
  291. v.X.Subtract(&XplusYsq, &v.Y)
  292. v.T.Subtract(&ZZ2, &v.Z)
  293. return v
  294. }
  295. // Negation.
  296. // Negate sets v = -p, and returns v.
  297. func (v *Point) Negate(p *Point) *Point {
  298. checkInitialized(p)
  299. v.x.Negate(&p.x)
  300. v.y.Set(&p.y)
  301. v.z.Set(&p.z)
  302. v.t.Negate(&p.t)
  303. return v
  304. }
  305. // Equal returns 1 if v is equivalent to u, and 0 otherwise.
  306. func (v *Point) Equal(u *Point) int {
  307. checkInitialized(v, u)
  308. var t1, t2, t3, t4 field.Element
  309. t1.Multiply(&v.x, &u.z)
  310. t2.Multiply(&u.x, &v.z)
  311. t3.Multiply(&v.y, &u.z)
  312. t4.Multiply(&u.y, &v.z)
  313. return t1.Equal(&t2) & t3.Equal(&t4)
  314. }
  315. // Constant-time operations
  316. // Select sets v to a if cond == 1 and to b if cond == 0.
  317. func (v *projCached) Select(a, b *projCached, cond int) *projCached {
  318. v.YplusX.Select(&a.YplusX, &b.YplusX, cond)
  319. v.YminusX.Select(&a.YminusX, &b.YminusX, cond)
  320. v.Z.Select(&a.Z, &b.Z, cond)
  321. v.T2d.Select(&a.T2d, &b.T2d, cond)
  322. return v
  323. }
  324. // Select sets v to a if cond == 1 and to b if cond == 0.
  325. func (v *affineCached) Select(a, b *affineCached, cond int) *affineCached {
  326. v.YplusX.Select(&a.YplusX, &b.YplusX, cond)
  327. v.YminusX.Select(&a.YminusX, &b.YminusX, cond)
  328. v.T2d.Select(&a.T2d, &b.T2d, cond)
  329. return v
  330. }
  331. // CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0.
  332. func (v *projCached) CondNeg(cond int) *projCached {
  333. v.YplusX.Swap(&v.YminusX, cond)
  334. v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond)
  335. return v
  336. }
  337. // CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0.
  338. func (v *affineCached) CondNeg(cond int) *affineCached {
  339. v.YplusX.Swap(&v.YminusX, cond)
  340. v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond)
  341. return v
  342. }