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. "crypto/ed25519/internal/edwards25519/field"
  7. "errors"
  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. // The point is internally represented in extended coordinates (X, Y, Z, T)
  24. // where x = X/Z, y = Y/Z, and xy = T/Z per https://eprint.iacr.org/2008/522.
  25. x, y, z, t field.Element
  26. // Make the type not comparable (i.e. used with == or as a map key), as
  27. // equivalent points can be represented by different Go values.
  28. _ incomparable
  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. // This is consistent with crypto/ed25519/internal/edwards25519. Read more
  123. // at https://hdevalence.ca/blog/2020-10-04-its-25519am, specifically the
  124. // "Canonical A, R" section.
  125. if len(x) != 32 {
  126. return nil, errors.New("edwards25519: invalid point encoding length")
  127. }
  128. y := new(field.Element).SetBytes(x)
  129. // -x² + y² = 1 + dx²y²
  130. // x² + dx²y² = x²(dy² + 1) = y² - 1
  131. // x² = (y² - 1) / (dy² + 1)
  132. // u = y² - 1
  133. y2 := new(field.Element).Square(y)
  134. u := new(field.Element).Subtract(y2, feOne)
  135. // v = dy² + 1
  136. vv := new(field.Element).Multiply(y2, d)
  137. vv = vv.Add(vv, feOne)
  138. // x = +√(u/v)
  139. xx, wasSquare := new(field.Element).SqrtRatio(u, vv)
  140. if wasSquare == 0 {
  141. return nil, errors.New("edwards25519: invalid point encoding")
  142. }
  143. // Select the negative square root if the sign bit is set.
  144. xxNeg := new(field.Element).Negate(xx)
  145. xx = xx.Select(xxNeg, xx, int(x[31]>>7))
  146. v.x.Set(xx)
  147. v.y.Set(y)
  148. v.z.One()
  149. v.t.Multiply(xx, y) // xy = T / Z
  150. return v, nil
  151. }
  152. func copyFieldElement(buf *[32]byte, v *field.Element) []byte {
  153. copy(buf[:], v.Bytes())
  154. return buf[:]
  155. }
  156. // Conversions.
  157. func (v *projP2) FromP1xP1(p *projP1xP1) *projP2 {
  158. v.X.Multiply(&p.X, &p.T)
  159. v.Y.Multiply(&p.Y, &p.Z)
  160. v.Z.Multiply(&p.Z, &p.T)
  161. return v
  162. }
  163. func (v *projP2) FromP3(p *Point) *projP2 {
  164. v.X.Set(&p.x)
  165. v.Y.Set(&p.y)
  166. v.Z.Set(&p.z)
  167. return v
  168. }
  169. func (v *Point) fromP1xP1(p *projP1xP1) *Point {
  170. v.x.Multiply(&p.X, &p.T)
  171. v.y.Multiply(&p.Y, &p.Z)
  172. v.z.Multiply(&p.Z, &p.T)
  173. v.t.Multiply(&p.X, &p.Y)
  174. return v
  175. }
  176. func (v *Point) fromP2(p *projP2) *Point {
  177. v.x.Multiply(&p.X, &p.Z)
  178. v.y.Multiply(&p.Y, &p.Z)
  179. v.z.Square(&p.Z)
  180. v.t.Multiply(&p.X, &p.Y)
  181. return v
  182. }
  183. // d is a constant in the curve equation.
  184. var d = new(field.Element).SetBytes([]byte{
  185. 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
  186. 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
  187. 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
  188. 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52})
  189. var d2 = new(field.Element).Add(d, d)
  190. func (v *projCached) FromP3(p *Point) *projCached {
  191. v.YplusX.Add(&p.y, &p.x)
  192. v.YminusX.Subtract(&p.y, &p.x)
  193. v.Z.Set(&p.z)
  194. v.T2d.Multiply(&p.t, d2)
  195. return v
  196. }
  197. func (v *affineCached) FromP3(p *Point) *affineCached {
  198. v.YplusX.Add(&p.y, &p.x)
  199. v.YminusX.Subtract(&p.y, &p.x)
  200. v.T2d.Multiply(&p.t, d2)
  201. var invZ field.Element
  202. invZ.Invert(&p.z)
  203. v.YplusX.Multiply(&v.YplusX, &invZ)
  204. v.YminusX.Multiply(&v.YminusX, &invZ)
  205. v.T2d.Multiply(&v.T2d, &invZ)
  206. return v
  207. }
  208. // (Re)addition and subtraction.
  209. // Add sets v = p + q, and returns v.
  210. func (v *Point) Add(p, q *Point) *Point {
  211. checkInitialized(p, q)
  212. qCached := new(projCached).FromP3(q)
  213. result := new(projP1xP1).Add(p, qCached)
  214. return v.fromP1xP1(result)
  215. }
  216. // Subtract sets v = p - q, and returns v.
  217. func (v *Point) Subtract(p, q *Point) *Point {
  218. checkInitialized(p, q)
  219. qCached := new(projCached).FromP3(q)
  220. result := new(projP1xP1).Sub(p, qCached)
  221. return v.fromP1xP1(result)
  222. }
  223. func (v *projP1xP1) Add(p *Point, q *projCached) *projP1xP1 {
  224. var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element
  225. YplusX.Add(&p.y, &p.x)
  226. YminusX.Subtract(&p.y, &p.x)
  227. PP.Multiply(&YplusX, &q.YplusX)
  228. MM.Multiply(&YminusX, &q.YminusX)
  229. TT2d.Multiply(&p.t, &q.T2d)
  230. ZZ2.Multiply(&p.z, &q.Z)
  231. ZZ2.Add(&ZZ2, &ZZ2)
  232. v.X.Subtract(&PP, &MM)
  233. v.Y.Add(&PP, &MM)
  234. v.Z.Add(&ZZ2, &TT2d)
  235. v.T.Subtract(&ZZ2, &TT2d)
  236. return v
  237. }
  238. func (v *projP1xP1) Sub(p *Point, q *projCached) *projP1xP1 {
  239. var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element
  240. YplusX.Add(&p.y, &p.x)
  241. YminusX.Subtract(&p.y, &p.x)
  242. PP.Multiply(&YplusX, &q.YminusX) // flipped sign
  243. MM.Multiply(&YminusX, &q.YplusX) // flipped sign
  244. TT2d.Multiply(&p.t, &q.T2d)
  245. ZZ2.Multiply(&p.z, &q.Z)
  246. ZZ2.Add(&ZZ2, &ZZ2)
  247. v.X.Subtract(&PP, &MM)
  248. v.Y.Add(&PP, &MM)
  249. v.Z.Subtract(&ZZ2, &TT2d) // flipped sign
  250. v.T.Add(&ZZ2, &TT2d) // flipped sign
  251. return v
  252. }
  253. func (v *projP1xP1) AddAffine(p *Point, q *affineCached) *projP1xP1 {
  254. var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element
  255. YplusX.Add(&p.y, &p.x)
  256. YminusX.Subtract(&p.y, &p.x)
  257. PP.Multiply(&YplusX, &q.YplusX)
  258. MM.Multiply(&YminusX, &q.YminusX)
  259. TT2d.Multiply(&p.t, &q.T2d)
  260. Z2.Add(&p.z, &p.z)
  261. v.X.Subtract(&PP, &MM)
  262. v.Y.Add(&PP, &MM)
  263. v.Z.Add(&Z2, &TT2d)
  264. v.T.Subtract(&Z2, &TT2d)
  265. return v
  266. }
  267. func (v *projP1xP1) SubAffine(p *Point, q *affineCached) *projP1xP1 {
  268. var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element
  269. YplusX.Add(&p.y, &p.x)
  270. YminusX.Subtract(&p.y, &p.x)
  271. PP.Multiply(&YplusX, &q.YminusX) // flipped sign
  272. MM.Multiply(&YminusX, &q.YplusX) // flipped sign
  273. TT2d.Multiply(&p.t, &q.T2d)
  274. Z2.Add(&p.z, &p.z)
  275. v.X.Subtract(&PP, &MM)
  276. v.Y.Add(&PP, &MM)
  277. v.Z.Subtract(&Z2, &TT2d) // flipped sign
  278. v.T.Add(&Z2, &TT2d) // flipped sign
  279. return v
  280. }
  281. // Doubling.
  282. func (v *projP1xP1) Double(p *projP2) *projP1xP1 {
  283. var XX, YY, ZZ2, XplusYsq field.Element
  284. XX.Square(&p.X)
  285. YY.Square(&p.Y)
  286. ZZ2.Square(&p.Z)
  287. ZZ2.Add(&ZZ2, &ZZ2)
  288. XplusYsq.Add(&p.X, &p.Y)
  289. XplusYsq.Square(&XplusYsq)
  290. v.Y.Add(&YY, &XX)
  291. v.Z.Subtract(&YY, &XX)
  292. v.X.Subtract(&XplusYsq, &v.Y)
  293. v.T.Subtract(&ZZ2, &v.Z)
  294. return v
  295. }
  296. // Negation.
  297. // Negate sets v = -p, and returns v.
  298. func (v *Point) Negate(p *Point) *Point {
  299. checkInitialized(p)
  300. v.x.Negate(&p.x)
  301. v.y.Set(&p.y)
  302. v.z.Set(&p.z)
  303. v.t.Negate(&p.t)
  304. return v
  305. }
  306. // Equal returns 1 if v is equivalent to u, and 0 otherwise.
  307. func (v *Point) Equal(u *Point) int {
  308. checkInitialized(v, u)
  309. var t1, t2, t3, t4 field.Element
  310. t1.Multiply(&v.x, &u.z)
  311. t2.Multiply(&u.x, &v.z)
  312. t3.Multiply(&v.y, &u.z)
  313. t4.Multiply(&u.y, &v.z)
  314. return t1.Equal(&t2) & t3.Equal(&t4)
  315. }
  316. // Constant-time operations
  317. // Select sets v to a if cond == 1 and to b if cond == 0.
  318. func (v *projCached) Select(a, b *projCached, cond int) *projCached {
  319. v.YplusX.Select(&a.YplusX, &b.YplusX, cond)
  320. v.YminusX.Select(&a.YminusX, &b.YminusX, cond)
  321. v.Z.Select(&a.Z, &b.Z, cond)
  322. v.T2d.Select(&a.T2d, &b.T2d, cond)
  323. return v
  324. }
  325. // Select sets v to a if cond == 1 and to b if cond == 0.
  326. func (v *affineCached) Select(a, b *affineCached, cond int) *affineCached {
  327. v.YplusX.Select(&a.YplusX, &b.YplusX, cond)
  328. v.YminusX.Select(&a.YminusX, &b.YminusX, cond)
  329. v.T2d.Select(&a.T2d, &b.T2d, cond)
  330. return v
  331. }
  332. // CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0.
  333. func (v *projCached) CondNeg(cond int) *projCached {
  334. v.YplusX.Swap(&v.YminusX, cond)
  335. v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond)
  336. return v
  337. }
  338. // CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0.
  339. func (v *affineCached) CondNeg(cond int) *affineCached {
  340. v.YplusX.Swap(&v.YminusX, cond)
  341. v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond)
  342. return v
  343. }