Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

isogeny.go 7.2 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package cln16sidh
  2. // Represents a 3-isogeny phi, holding the data necessary to evaluate phi.
  3. type ThreeIsogeny struct {
  4. x ExtensionFieldElement
  5. z ExtensionFieldElement
  6. }
  7. // Given a three-torsion point x3 = x(P_3) on the curve E_(A:C), construct the
  8. // three-isogeny phi : E_(A:C) -> E_(A:C)/<P_3> = E_(A':C').
  9. //
  10. // Returns a tuple (codomain, isogeny) = (E_(A':C'), phi).
  11. func ComputeThreeIsogeny(x3 *ProjectivePoint) (ProjectiveCurveParameters, ThreeIsogeny) {
  12. var isogeny ThreeIsogeny
  13. isogeny.x = x3.x
  14. isogeny.z = x3.z
  15. // We want to compute
  16. // (A':C') = (Z^4 + 18X^2Z^2 - 27X^4 : 4XZ^3)
  17. // To do this, use the identity 18X^2Z^2 - 27X^4 = 9X^2(2Z^2 - 3X^2)
  18. var codomain ProjectiveCurveParameters
  19. var v0, v1, v2, v3 ExtensionFieldElement
  20. v1.Square(&x3.x) // = X^2
  21. v0.Add(&v1, &v1).Add(&v1, &v0) // = 3X^2
  22. v1.Add(&v0, &v0).Add(&v1, &v0) // = 9X^2
  23. v2.Square(&x3.z) // = Z^2
  24. v3.Square(&v2) // = Z^4
  25. v2.Add(&v2, &v2) // = 2Z^2
  26. v0.Sub(&v2, &v0) // = 2Z^2 - 3X^2
  27. v1.Mul(&v1, &v0) // = 9X^2(2Z^2 - 3X^2)
  28. v0.Mul(&x3.x, &x3.z) // = XZ
  29. v0.Add(&v0, &v0) // = 2XZ
  30. codomain.A.Add(&v3, &v1) // = Z^4 + 9X^2(2Z^2 - 3X^2)
  31. codomain.C.Mul(&v0, &v2) // = 4XZ^3
  32. return codomain, isogeny
  33. }
  34. // Given a 3-isogeny phi and a point xP = x(P), compute x(Q), the x-coordinate
  35. // of the image Q = phi(P) of P under phi : E_(A:C) -> E_(A':C').
  36. //
  37. // The output xQ = x(Q) is then a point on the curve E_(A':C'); the curve
  38. // parameters are returned by the Compute3Isogeny function used to construct
  39. // phi.
  40. func (phi *ThreeIsogeny) Eval(xP *ProjectivePoint) ProjectivePoint {
  41. var xQ ProjectivePoint
  42. var t0, t1, t2 ExtensionFieldElement
  43. t0.Mul(&phi.x, &xP.x) // = X3*XP
  44. t1.Mul(&phi.z, &xP.z) // = Z3*XP
  45. t2.Sub(&t0, &t1) // = X3*XP - Z3*ZP
  46. t0.Mul(&phi.z, &xP.x) // = Z3*XP
  47. t1.Mul(&phi.x, &xP.z) // = X3*ZP
  48. t0.Sub(&t0, &t1) // = Z3*XP - X3*ZP
  49. t2.Square(&t2) // = (X3*XP - Z3*ZP)^2
  50. t0.Square(&t0) // = (Z3*XP - X3*ZP)^2
  51. xQ.x.Mul(&t2, &xP.x) // = XP*(X3*XP - Z3*ZP)^2
  52. xQ.z.Mul(&t0, &xP.z) // = ZP*(Z3*XP - X3*ZP)^2
  53. return xQ
  54. }
  55. // Represents a 4-isogeny phi, holding the data necessary to evaluate phi.
  56. type FourIsogeny struct {
  57. Xsq_plus_Zsq ExtensionFieldElement
  58. Xsq_minus_Zsq ExtensionFieldElement
  59. XZ2 ExtensionFieldElement
  60. Xpow4 ExtensionFieldElement
  61. Zpow4 ExtensionFieldElement
  62. }
  63. // Given a four-torsion point x4 = x(P_4) on the curve E_(A:C), compute the
  64. // coefficients of the codomain E_(A':C') of the four-isogeny phi : E_(A:C) ->
  65. // E_(A:C)/<P_4>.
  66. //
  67. // Returns a tuple (codomain, isogeny) = (E_(A':C') : phi).
  68. //
  69. // XXX write up a better explanation of what's going on here
  70. func ComputeFourIsogeny(x4 *ProjectivePoint) (ProjectiveCurveParameters, FourIsogeny) {
  71. var codomain ProjectiveCurveParameters
  72. var isogeny FourIsogeny
  73. var v0, v1 ExtensionFieldElement
  74. v0.Square(&x4.x) // = X4^2
  75. v1.Square(&x4.z) // = Z4^2
  76. isogeny.Xsq_plus_Zsq.Add(&v0, &v1) // = X4^2 + Z4^2
  77. isogeny.Xsq_minus_Zsq.Sub(&v0, &v1) // = X4^2 - Z4^2
  78. isogeny.XZ2.Add(&x4.x, &x4.z) // = X4 + Z4
  79. isogeny.XZ2.Square(&isogeny.XZ2) // = X4^2 + Z4^2 + 2X4Z4
  80. isogeny.XZ2.Sub(&isogeny.XZ2, &isogeny.Xsq_plus_Zsq) // = 2X4Z4
  81. isogeny.Xpow4.Square(&v0) // = X4^4
  82. isogeny.Zpow4.Square(&v1) // = Z4^4
  83. v0.Add(&isogeny.Xpow4, &isogeny.Xpow4) // = 2X4^4
  84. v0.Sub(&v0, &isogeny.Zpow4) // = 2X4^4 - Z4^4
  85. codomain.A.Add(&v0, &v0) // = 2(2X4^4 - Z4^4)
  86. codomain.C = isogeny.Zpow4 // = Z4^4
  87. return codomain, isogeny
  88. }
  89. // Given a 4-isogeny phi and a point xP = x(P), compute x(Q), the x-coordinate
  90. // of the image Q = phi(P) of P under phi : E_(A:C) -> E_(A':C').
  91. //
  92. // The output xQ = x(Q) is then a point on the curve E_(A':C'); the curve
  93. // parameters are returned by the ComputeFourIsogeny function used to construct
  94. // phi.
  95. func (phi *FourIsogeny) Eval(xP *ProjectivePoint) ProjectivePoint {
  96. var xQ ProjectivePoint
  97. var t0, t1, t2 ExtensionFieldElement
  98. // We want to compute formula (7) of Costello-Longa-Naehrig, namely
  99. //
  100. // Xprime = (2*X_4*Z*Z_4 - (X_4^2 + Z_4^2)*X)*(X*X_4 - Z*Z_4)^2*X
  101. // Zprime = (2*X*X_4*Z_4 - (X_4^2 + Z_4^2)*Z)*(X_4*Z - X*Z_4)^2*Z
  102. //
  103. // To do this we adapt the method in the MSR implementation, which computes
  104. //
  105. // X_Q = Xprime*( 16*(X_4 + Z_4)*(X_4 - Z_4)*X_4^2*Z_4^4 )
  106. // Z_Q = Zprime*( 16*(X_4 + Z_4)*(X_4 - Z_4)*X_4^2*Z_4^4 )
  107. //
  108. t0.Mul(&xP.x, &phi.XZ2) // = 2*X*X_4*Z_4
  109. t1.Mul(&xP.z, &phi.Xsq_plus_Zsq) // = (X_4^2 + Z_4^2)*Z
  110. t0.Sub(&t0, &t1) // = -X_4^2*Z + 2*X*X_4*Z_4 - Z*Z_4^2
  111. t1.Mul(&xP.z, &phi.Xsq_minus_Zsq) // = (X_4^2 - Z_4^2)*Z
  112. t2.Sub(&t0, &t1).Square(&t2) // = 4*(X_4*Z - X*Z_4)^2*X_4^2
  113. t0.Mul(&t0, &t1).Add(&t0, &t0).Add(&t0, &t0) // = 4*(2*X*X_4*Z_4 - (X_4^2 + Z_4^2)*Z)*(X_4^2 - Z_4^2)*Z
  114. t1.Add(&t0, &t2) // = 4*(X*X_4 - Z*Z_4)^2*Z_4^2
  115. t0.Mul(&t0, &t2) // = Zprime * 16*(X_4 + Z_4)*(X_4 - Z_4)*X_4^2
  116. xQ.z.Mul(&t0, &phi.Zpow4) // = Zprime * 16*(X_4 + Z_4)*(X_4 - Z_4)*X_4^2*Z_4^4
  117. t2.Mul(&t2, &phi.Zpow4) // = 4*(X_4*Z - X*Z_4)^2*X_4^2*Z_4^4
  118. t0.Mul(&t1, &phi.Xpow4) // = 4*(X*X_4 - Z*Z_4)^2*X_4^4*Z_4^2
  119. t0.Sub(&t2, &t0) // = -4*(X*X_4^2 - 2*X_4*Z*Z_4 + X*Z_4^2)*X*(X_4^2 - Z_4^2)*X_4^2*Z_4^2
  120. xQ.x.Mul(&t1, &t0) // = Xprime * 16*(X_4 + Z_4)*(X_4 - Z_4)*X_4^2*Z_4^4
  121. return xQ
  122. }
  123. // XXX document/explain how this is different from FourIsogeny and why it's needed
  124. type FirstFourIsogeny struct {
  125. A ExtensionFieldElement
  126. C ExtensionFieldElement
  127. }
  128. func ComputeFirstFourIsogeny(domain *ProjectiveCurveParameters) (ProjectiveCurveParameters, FirstFourIsogeny) {
  129. var codomain ProjectiveCurveParameters
  130. var isogeny FirstFourIsogeny
  131. var t0, t1 ExtensionFieldElement
  132. t0.Add(&domain.C, &domain.C) // = 2*C
  133. codomain.C.Sub(&domain.A, &t0) // = A - 2*C
  134. t1.Add(&t0, &t0) // = 4*C
  135. t1.Add(&t1, &t0) // = 6*C
  136. t0.Add(&t1, &domain.A) // = A + 6*C
  137. codomain.A.Add(&t0, &t0) // = 2*(A + 6*C)
  138. isogeny.A = domain.A
  139. isogeny.C = domain.C
  140. return codomain, isogeny
  141. }
  142. func (phi *FirstFourIsogeny) Eval(xP *ProjectivePoint) ProjectivePoint {
  143. var xQ ProjectivePoint
  144. var t0, t1, t2, t3 ExtensionFieldElement
  145. t0.Add(&xP.x, &xP.z).Square(&t0) // = (X+Z)^2
  146. t2.Mul(&xP.x, &xP.z) // = X*Z
  147. t1.Add(&t2, &t2) // = 2*X*Z
  148. t1.Sub(&t0, &t1) // = X^2 + Z^2
  149. xQ.x.Mul(&phi.A, &t2) // = A*X*Z
  150. t3.Mul(&phi.C, &t1) // = C*(X^2 + Z^2)
  151. xQ.x.Add(&xQ.x, &t3) // = A*X*Z + C*(X^2 + Z^2)
  152. xQ.x.Mul(&xQ.x, &t0) // = (X+Z)^2 * (A*X*Z + C*(X^2 + Z^2))
  153. t0.Sub(&xP.x, &xP.z).Square(&t0) // = (X-Z)^2
  154. t0.Mul(&t0, &t2) // = X*Z*(X-Z)^2
  155. t1.Add(&phi.C, &phi.C) // = 2*C
  156. t1.Sub(&t1, &phi.A) // = 2*C - A
  157. xQ.z.Mul(&t1, &t0) // = (2*C - A)*X*Z*(X-Z)^2
  158. return xQ
  159. }