Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

303 linhas
9.3 KiB

  1. package sidh
  2. import (
  3. . "github.com/cloudflare/p751sidh/internal/isogeny"
  4. )
  5. // -----------------------------------------------------------------------------
  6. // Functions for traversing isogeny trees acoording to strategy. Key type 'A' is
  7. //
  8. // Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
  9. // for public key generation.
  10. func traverseTreePublicKeyA(curve *ProjectiveCurveParameters, xR, phiP, phiQ, phiR *ProjectivePoint, pub *PublicKey) {
  11. var points = make([]ProjectivePoint, 0, 8)
  12. var indices = make([]int, 0, 8)
  13. var i, sidx int
  14. var op = CurveOperations{Params: pub.params}
  15. cparam := op.CalcCurveParamsEquiv4(curve)
  16. phi := Newisogeny4(op.Params.Op)
  17. strat := pub.params.A.IsogenyStrategy
  18. stratSz := len(strat)
  19. for j := 1; j <= stratSz; j++ {
  20. for i <= stratSz-j {
  21. points = append(points, *xR)
  22. indices = append(indices, i)
  23. k := strat[sidx]
  24. sidx++
  25. op.Pow2k(xR, &cparam, 2*k)
  26. i += int(k)
  27. }
  28. cparam = phi.GenerateCurve(xR)
  29. for k := 0; k < len(points); k++ {
  30. points[k] = phi.EvaluatePoint(&points[k])
  31. }
  32. *phiP = phi.EvaluatePoint(phiP)
  33. *phiQ = phi.EvaluatePoint(phiQ)
  34. *phiR = phi.EvaluatePoint(phiR)
  35. // pop xR from points
  36. *xR, points = points[len(points)-1], points[:len(points)-1]
  37. i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
  38. }
  39. }
  40. // Traverses isogeny tree in order to compute xR needed
  41. // for public key generation.
  42. func traverseTreeSharedKeyA(curve *ProjectiveCurveParameters, xR *ProjectivePoint, pub *PublicKey) {
  43. var points = make([]ProjectivePoint, 0, 8)
  44. var indices = make([]int, 0, 8)
  45. var i, sidx int
  46. var op = CurveOperations{Params: pub.params}
  47. cparam := op.CalcCurveParamsEquiv4(curve)
  48. phi := Newisogeny4(op.Params.Op)
  49. strat := pub.params.A.IsogenyStrategy
  50. stratSz := len(strat)
  51. for j := 1; j <= stratSz; j++ {
  52. for i <= stratSz-j {
  53. points = append(points, *xR)
  54. indices = append(indices, i)
  55. k := strat[sidx]
  56. sidx++
  57. op.Pow2k(xR, &cparam, 2*k)
  58. i += int(k)
  59. }
  60. cparam = phi.GenerateCurve(xR)
  61. for k := 0; k < len(points); k++ {
  62. points[k] = phi.EvaluatePoint(&points[k])
  63. }
  64. // pop xR from points
  65. *xR, points = points[len(points)-1], points[:len(points)-1]
  66. i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
  67. }
  68. }
  69. // Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
  70. // for public key generation.
  71. func traverseTreePublicKeyB(curve *ProjectiveCurveParameters, xR, phiP, phiQ, phiR *ProjectivePoint, pub *PublicKey) {
  72. var points = make([]ProjectivePoint, 0, 8)
  73. var indices = make([]int, 0, 8)
  74. var i, sidx int
  75. var op = CurveOperations{Params: pub.params}
  76. cparam := op.CalcCurveParamsEquiv3(curve)
  77. phi := Newisogeny3(op.Params.Op)
  78. strat := pub.params.B.IsogenyStrategy
  79. stratSz := len(strat)
  80. for j := 1; j <= stratSz; j++ {
  81. for i <= stratSz-j {
  82. points = append(points, *xR)
  83. indices = append(indices, i)
  84. k := strat[sidx]
  85. sidx++
  86. op.Pow3k(xR, &cparam, k)
  87. i += int(k)
  88. }
  89. cparam = phi.GenerateCurve(xR)
  90. for k := 0; k < len(points); k++ {
  91. points[k] = phi.EvaluatePoint(&points[k])
  92. }
  93. *phiP = phi.EvaluatePoint(phiP)
  94. *phiQ = phi.EvaluatePoint(phiQ)
  95. *phiR = phi.EvaluatePoint(phiR)
  96. // pop xR from points
  97. *xR, points = points[len(points)-1], points[:len(points)-1]
  98. i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
  99. }
  100. }
  101. // Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
  102. // for public key generation.
  103. func traverseTreeSharedKeyB(curve *ProjectiveCurveParameters, xR *ProjectivePoint, pub *PublicKey) {
  104. var points = make([]ProjectivePoint, 0, 8)
  105. var indices = make([]int, 0, 8)
  106. var i, sidx int
  107. var op = CurveOperations{Params: pub.params}
  108. cparam := op.CalcCurveParamsEquiv3(curve)
  109. phi := Newisogeny3(op.Params.Op)
  110. strat := pub.params.B.IsogenyStrategy
  111. stratSz := len(strat)
  112. for j := 1; j <= stratSz; j++ {
  113. for i <= stratSz-j {
  114. points = append(points, *xR)
  115. indices = append(indices, i)
  116. k := strat[sidx]
  117. sidx++
  118. op.Pow3k(xR, &cparam, k)
  119. i += int(k)
  120. }
  121. cparam = phi.GenerateCurve(xR)
  122. for k := 0; k < len(points); k++ {
  123. points[k] = phi.EvaluatePoint(&points[k])
  124. }
  125. // pop xR from points
  126. *xR, points = points[len(points)-1], points[:len(points)-1]
  127. i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
  128. }
  129. }
  130. // Generate a public key in the 2-torsion group
  131. func publicKeyGenA(prv *PrivateKey) (pub *PublicKey) {
  132. var xPA, xQA, xRA ProjectivePoint
  133. var xPB, xQB, xRB, xR ProjectivePoint
  134. var invZP, invZQ, invZR Fp2Element
  135. var tmp ProjectiveCurveParameters
  136. pub = NewPublicKey(prv.params.Id, KeyVariant_SIDH_A)
  137. var op = CurveOperations{Params: pub.params}
  138. var phi = Newisogeny4(op.Params.Op)
  139. // Load points for A
  140. xPA = ProjectivePoint{X: prv.params.A.Affine_P, Z: prv.params.OneFp2}
  141. xQA = ProjectivePoint{X: prv.params.A.Affine_Q, Z: prv.params.OneFp2}
  142. xRA = ProjectivePoint{X: prv.params.A.Affine_R, Z: prv.params.OneFp2}
  143. // Load points for B
  144. xRB = ProjectivePoint{X: prv.params.B.Affine_R, Z: prv.params.OneFp2}
  145. xQB = ProjectivePoint{X: prv.params.B.Affine_Q, Z: prv.params.OneFp2}
  146. xPB = ProjectivePoint{X: prv.params.B.Affine_P, Z: prv.params.OneFp2}
  147. // Find isogeny kernel
  148. tmp.C = pub.params.OneFp2
  149. xR = op.ScalarMul3Pt(&tmp, &xPA, &xQA, &xRA, prv.params.A.SecretBitLen, prv.Scalar)
  150. // Reset params object and travers isogeny tree
  151. tmp.C = pub.params.OneFp2
  152. tmp.A.Zeroize()
  153. traverseTreePublicKeyA(&tmp, &xR, &xPB, &xQB, &xRB, pub)
  154. // Secret isogeny
  155. phi.GenerateCurve(&xR)
  156. xPA = phi.EvaluatePoint(&xPB)
  157. xQA = phi.EvaluatePoint(&xQB)
  158. xRA = phi.EvaluatePoint(&xRB)
  159. op.Fp2Batch3Inv(&xPA.Z, &xQA.Z, &xRA.Z, &invZP, &invZQ, &invZR)
  160. op.Params.Op.Mul(&pub.affine_xP, &xPA.X, &invZP)
  161. op.Params.Op.Mul(&pub.affine_xQ, &xQA.X, &invZQ)
  162. op.Params.Op.Mul(&pub.affine_xQmP, &xRA.X, &invZR)
  163. return
  164. }
  165. // Generate a public key in the 3-torsion group
  166. func publicKeyGenB(prv *PrivateKey) (pub *PublicKey) {
  167. var xPB, xQB, xRB, xR ProjectivePoint
  168. var xPA, xQA, xRA ProjectivePoint
  169. var invZP, invZQ, invZR Fp2Element
  170. var tmp ProjectiveCurveParameters
  171. pub = NewPublicKey(prv.params.Id, prv.keyVariant)
  172. var op = CurveOperations{Params: pub.params}
  173. var phi = Newisogeny3(op.Params.Op)
  174. // Load points for B
  175. xRB = ProjectivePoint{X: prv.params.B.Affine_R, Z: prv.params.OneFp2}
  176. xQB = ProjectivePoint{X: prv.params.B.Affine_Q, Z: prv.params.OneFp2}
  177. xPB = ProjectivePoint{X: prv.params.B.Affine_P, Z: prv.params.OneFp2}
  178. // Load points for A
  179. xPA = ProjectivePoint{X: prv.params.A.Affine_P, Z: prv.params.OneFp2}
  180. xQA = ProjectivePoint{X: prv.params.A.Affine_Q, Z: prv.params.OneFp2}
  181. xRA = ProjectivePoint{X: prv.params.A.Affine_R, Z: prv.params.OneFp2}
  182. tmp.C = pub.params.OneFp2
  183. xR = op.ScalarMul3Pt(&tmp, &xPB, &xQB, &xRB, prv.params.B.SecretBitLen, prv.Scalar)
  184. tmp.C = pub.params.OneFp2
  185. tmp.A.Zeroize()
  186. traverseTreePublicKeyB(&tmp, &xR, &xPA, &xQA, &xRA, pub)
  187. phi.GenerateCurve(&xR)
  188. xPB = phi.EvaluatePoint(&xPA)
  189. xQB = phi.EvaluatePoint(&xQA)
  190. xRB = phi.EvaluatePoint(&xRA)
  191. op.Fp2Batch3Inv(&xPB.Z, &xQB.Z, &xRB.Z, &invZP, &invZQ, &invZR)
  192. op.Params.Op.Mul(&pub.affine_xP, &xPB.X, &invZP)
  193. op.Params.Op.Mul(&pub.affine_xQ, &xQB.X, &invZQ)
  194. op.Params.Op.Mul(&pub.affine_xQmP, &xRB.X, &invZR)
  195. return
  196. }
  197. // -----------------------------------------------------------------------------
  198. // Key agreement functions
  199. //
  200. // Establishing shared keys in in 2-torsion group
  201. func deriveSecretA(prv *PrivateKey, pub *PublicKey) []byte {
  202. var sharedSecret = make([]byte, pub.params.SharedSecretSize)
  203. var cparam ProjectiveCurveParameters
  204. var xP, xQ, xQmP ProjectivePoint
  205. var xR ProjectivePoint
  206. var op = CurveOperations{Params: prv.params}
  207. var phi = Newisogeny4(op.Params.Op)
  208. // Recover curve coefficients
  209. cparam.C = pub.params.OneFp2
  210. op.RecoverCoordinateA(&cparam, &pub.affine_xP, &pub.affine_xQ, &pub.affine_xQmP)
  211. // Find kernel of the morphism
  212. xP = ProjectivePoint{X: pub.affine_xP, Z: pub.params.OneFp2}
  213. xQ = ProjectivePoint{X: pub.affine_xQ, Z: pub.params.OneFp2}
  214. xQmP = ProjectivePoint{X: pub.affine_xQmP, Z: pub.params.OneFp2}
  215. xR = op.ScalarMul3Pt(&cparam, &xP, &xQ, &xQmP, pub.params.A.SecretBitLen, prv.Scalar)
  216. // Traverse isogeny tree
  217. traverseTreeSharedKeyA(&cparam, &xR, pub)
  218. // Calculate j-invariant on isogeneus curve
  219. c := phi.GenerateCurve(&xR)
  220. op.RecoverCurveCoefficients4(&cparam, &c)
  221. op.Jinvariant(&cparam, sharedSecret)
  222. return sharedSecret
  223. }
  224. // Establishing shared keys in in 3-torsion group
  225. func deriveSecretB(prv *PrivateKey, pub *PublicKey) []byte {
  226. var sharedSecret = make([]byte, pub.params.SharedSecretSize)
  227. var xP, xQ, xQmP ProjectivePoint
  228. var xR ProjectivePoint
  229. var cparam ProjectiveCurveParameters
  230. var op = CurveOperations{Params: prv.params}
  231. var phi = Newisogeny3(op.Params.Op)
  232. // Recover curve coefficients
  233. cparam.C = pub.params.OneFp2
  234. op.RecoverCoordinateA(&cparam, &pub.affine_xP, &pub.affine_xQ, &pub.affine_xQmP)
  235. // Find kernel of the morphism
  236. xP = ProjectivePoint{X: pub.affine_xP, Z: pub.params.OneFp2}
  237. xQ = ProjectivePoint{X: pub.affine_xQ, Z: pub.params.OneFp2}
  238. xQmP = ProjectivePoint{X: pub.affine_xQmP, Z: pub.params.OneFp2}
  239. xR = op.ScalarMul3Pt(&cparam, &xP, &xQ, &xQmP, pub.params.B.SecretBitLen, prv.Scalar)
  240. // Traverse isogeny tree
  241. traverseTreeSharedKeyB(&cparam, &xR, pub)
  242. // Calculate j-invariant on isogeneus curve
  243. c := phi.GenerateCurve(&xR)
  244. op.RecoverCurveCoefficients3(&cparam, &c)
  245. op.Jinvariant(&cparam, sharedSecret)
  246. return sharedSecret
  247. }