Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 

429 righe
12 KiB

  1. package sidh
  2. import (
  3. "errors"
  4. "io"
  5. // TODO: This is needed by ExtensionFieldElement struct, which itself
  6. // depends on implementation of p751.
  7. // p503 "github.com/cloudflare/p751sidh/p503toolbox"
  8. p751 "github.com/cloudflare/p751sidh/p751toolbox"
  9. )
  10. // -----------------------------------------------------------------------------
  11. // Functions for traversing isogeny trees acoording to strategy. Key type 'A' is
  12. //
  13. // Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
  14. // for public key generation.
  15. func traverseTreePublicKeyA(curve *p751.ProjectiveCurveParameters, xR, phiP, phiQ, phiR *p751.ProjectivePoint, pub *PublicKey) {
  16. var points = make([]p751.ProjectivePoint, 0, 8)
  17. var indices = make([]int, 0, 8)
  18. var i, sidx int
  19. cparam := curve.CalcCurveParamsEquiv4()
  20. phi := p751.NewIsogeny4()
  21. strat := pub.params.A.IsogenyStrategy
  22. stratSz := len(strat)
  23. for j := 1; j <= stratSz; j++ {
  24. for i <= stratSz-j {
  25. points = append(points, *xR)
  26. indices = append(indices, i)
  27. k := strat[sidx]
  28. sidx++
  29. xR.Pow2k(&cparam, xR, 2*k)
  30. i += int(k)
  31. }
  32. cparam = phi.GenerateCurve(xR)
  33. for k := 0; k < len(points); k++ {
  34. points[k] = phi.EvaluatePoint(&points[k])
  35. }
  36. *phiP = phi.EvaluatePoint(phiP)
  37. *phiQ = phi.EvaluatePoint(phiQ)
  38. *phiR = phi.EvaluatePoint(phiR)
  39. // pop xR from points
  40. *xR, points = points[len(points)-1], points[:len(points)-1]
  41. i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
  42. }
  43. }
  44. // -----------------------------------------------------------------------------
  45. // Functions for traversing isogeny trees acoording to strategy. Key type 'A' is
  46. //
  47. // Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
  48. // for public key generation.
  49. func traverseTreePublicKeyAX(ctx *OperationContext, pub *PublicKey/*curve *p751.ProjectiveCurveParameters, xR, phiP, phiQ, phiR *p751.ProjectivePoint, */) {
  50. var points = make([]p751.ProjectivePoint, 0, 8)
  51. var indices = make([]int, 0, 8)
  52. var i, sidx int
  53. //cparam := curve.CalcCurveParamsEquiv4()
  54. phi := p751.NewIsogeny4()
  55. strat := pub.params.A.IsogenyStrategy
  56. stratSz := len(strat)
  57. for j := 1; j <= stratSz; j++ {
  58. for i <= stratSz-j {
  59. points = append(points, *xR)
  60. indices = append(indices, i)
  61. k := strat[sidx]
  62. sidx++
  63. xR.Pow2k(&cparam, xR, 2*k)
  64. i += int(k)
  65. }
  66. cparam = phi.GenerateCurve(xR)
  67. for k := 0; k < len(points); k++ {
  68. points[k] = phi.EvaluatePoint(&points[k])
  69. }
  70. *phiP = phi.EvaluatePoint(phiP)
  71. *phiQ = phi.EvaluatePoint(phiQ)
  72. *phiR = phi.EvaluatePoint(phiR)
  73. // pop xR from points
  74. *xR, points = points[len(points)-1], points[:len(points)-1]
  75. i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
  76. }
  77. }
  78. // Traverses isogeny tree in order to compute xR needed
  79. // for public key generation.
  80. func traverseTreeSharedKeyA(curve *p751.ProjectiveCurveParameters, xR *p751.ProjectivePoint, pub *PublicKey) {
  81. var points = make([]p751.ProjectivePoint, 0, 8)
  82. var indices = make([]int, 0, 8)
  83. var i, sidx int
  84. cparam := curve.CalcCurveParamsEquiv4()
  85. phi := p751.NewIsogeny4()
  86. strat := pub.params.A.IsogenyStrategy
  87. stratSz := len(strat)
  88. for j := 1; j <= stratSz; j++ {
  89. for i <= stratSz-j {
  90. points = append(points, *xR)
  91. indices = append(indices, i)
  92. k := strat[sidx]
  93. sidx++
  94. xR.Pow2k(&cparam, xR, 2*k)
  95. i += int(k)
  96. }
  97. cparam = phi.GenerateCurve(xR)
  98. for k := 0; k < len(points); k++ {
  99. points[k] = phi.EvaluatePoint(&points[k])
  100. }
  101. // pop xR from points
  102. *xR, points = points[len(points)-1], points[:len(points)-1]
  103. i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
  104. }
  105. }
  106. // Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
  107. // for public key generation.
  108. func traverseTreePublicKeyB(curve *p751.ProjectiveCurveParameters, xR, phiP, phiQ, phiR *p751.ProjectivePoint, pub *PublicKey) {
  109. var points = make([]p751.ProjectivePoint, 0, 8)
  110. var indices = make([]int, 0, 8)
  111. var i, sidx int
  112. cparam := curve.CalcCurveParamsEquiv3()
  113. phi := p751.NewIsogeny3()
  114. strat := pub.params.B.IsogenyStrategy
  115. stratSz := len(strat)
  116. for j := 1; j <= stratSz; j++ {
  117. for i <= stratSz-j {
  118. points = append(points, *xR)
  119. indices = append(indices, i)
  120. k := strat[sidx]
  121. sidx++
  122. xR.Pow3k(&cparam, xR, k)
  123. i += int(k)
  124. }
  125. cparam = phi.GenerateCurve(xR)
  126. for k := 0; k < len(points); k++ {
  127. points[k] = phi.EvaluatePoint(&points[k])
  128. }
  129. *phiP = phi.EvaluatePoint(phiP)
  130. *phiQ = phi.EvaluatePoint(phiQ)
  131. *phiR = phi.EvaluatePoint(phiR)
  132. // pop xR from points
  133. *xR, points = points[len(points)-1], points[:len(points)-1]
  134. i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
  135. }
  136. }
  137. // Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
  138. // for public key generation.
  139. func traverseTreeSharedKeyB(curve *p751.ProjectiveCurveParameters, xR *p751.ProjectivePoint, pub *PublicKey) {
  140. var points = make([]p751.ProjectivePoint, 0, 8)
  141. var indices = make([]int, 0, 8)
  142. var i, sidx int
  143. cparam := curve.CalcCurveParamsEquiv3()
  144. phi := p751.NewIsogeny3()
  145. strat := pub.params.B.IsogenyStrategy
  146. stratSz := len(strat)
  147. for j := 1; j <= stratSz; j++ {
  148. for i <= stratSz-j {
  149. points = append(points, *xR)
  150. indices = append(indices, i)
  151. k := strat[sidx]
  152. sidx++
  153. xR.Pow3k(&cparam, xR, k)
  154. i += int(k)
  155. }
  156. cparam = phi.GenerateCurve(xR)
  157. for k := 0; k < len(points); k++ {
  158. points[k] = phi.EvaluatePoint(&points[k])
  159. }
  160. // pop xR from points
  161. *xR, points = points[len(points)-1], points[:len(points)-1]
  162. i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
  163. }
  164. }
  165. // -----------------------------------------------------------------------------
  166. // Key generation functions
  167. //
  168. // Generate a private key for "Alice". Note that because this library does not
  169. // implement SIDH validation, each keypair must be used for at most one
  170. // shared secret computation.
  171. func (prv *PrivateKey) generatePrivateKeyA(rand io.Reader) error {
  172. _, err := io.ReadFull(rand, prv.Scalar)
  173. if err != nil {
  174. return err
  175. }
  176. // Bit-twiddle to ensure scalar is in 2*[0,2^371):
  177. prv.Scalar[prv.params.SecretKeySize-1] = prv.params.A.MaskBytes[0]
  178. prv.Scalar[prv.params.SecretKeySize-2] &= prv.params.A.MaskBytes[1] // clear high bits, so scalar < 2^372
  179. prv.Scalar[0] &= prv.params.A.MaskBytes[2] // clear low bit, so scalar is even
  180. // We actually want scalar in 2*(0,2^371), but the above procedure
  181. // generates 0 with probability 2^(-371), which isn't worth checking
  182. // for.
  183. return nil
  184. }
  185. // Generate a private key for "Bob". Note that because this library does not
  186. // implement SIDH validation, each keypair must be used for at most one
  187. // shared secret computation.
  188. func (prv *PrivateKey) generatePrivateKeyB(rand io.Reader) error {
  189. // Perform rejection sampling to obtain a random value in [0,3^238]:
  190. var ok uint8
  191. for i := uint(0); i < prv.params.SampleRate; i++ {
  192. _, err := io.ReadFull(rand, prv.Scalar)
  193. if err != nil {
  194. return err
  195. }
  196. // Mask the high bits to obtain a uniform value in [0,2^378):
  197. // TODO: simply run it in loop, if rand distribution is uniform you surelly get non 0
  198. // if not - better die, keep looping, hang, whatever, but don't generate secure key
  199. prv.Scalar[prv.params.SecretKeySize-1] &= prv.params.B.MaskBytes[0]
  200. // Accept if scalar < 3^238 (this happens w/ prob ~0.5828)
  201. // TODO this is specific to P751
  202. ok = checkLessThanThree238(prv.Scalar)
  203. if ok == 0 {
  204. break
  205. }
  206. }
  207. // ok is nonzero if all sampleRate trials failed.
  208. // This happens with probability 0.41719...^102 < 2^(-128), i.e., never
  209. if ok != 0 {
  210. // In case this happens user should retry. In practice it is highly
  211. // improbable (< 2^-128).
  212. return errors.New("sidh: private key generation failed")
  213. }
  214. // Multiply by 3 to get a scalar in 3*[0,3^238):
  215. multiplyByThree(prv.Scalar)
  216. // We actually want scalar in 2*(0,2^371), but the above procedure
  217. // generates 0 with probability 2^(-371), which isn't worth checking
  218. // for.
  219. return nil
  220. }
  221. // Generate a public key in the 2-torsion group
  222. func publicKeyGenA(prv *PrivateKey) (pub *PublicKey) {
  223. // var xPA, xQA, xRA p751.ProjectivePoint
  224. // var xPB, xQB, xRB, xR p751.ProjectivePoint
  225. // var invZP, invZQ, invZR p751.ExtensionFieldElement
  226. // var tmp p751.ProjectiveCurveParameters
  227. // var phi = p751.NewIsogeny4()
  228. //
  229. pub = NewPublicKey(prv.params.Id, KeyVariant_SIDH_A)
  230. ctx := prv.params.op()
  231. ctx.LoadBasePoints()
  232. ctx.ScalarMul(prv.Scalar, prv.params.A.SecretBitLen)
  233. traverseTreePublicKeyA(ctx)
  234. // ctx.CreateSecretIsogeny()
  235. // ctx.Store(pub)
  236. /*
  237. // Load points for A
  238. xPA.FromAffine(&prv.params.A.Affine_P)
  239. xPA.Z.One()
  240. xQA.FromAffine(&prv.params.A.Affine_Q)
  241. xQA.Z.One()
  242. xRA.FromAffine(&prv.params.A.Affine_R)
  243. xRA.Z.One()
  244. // Load points for B
  245. xRB.FromAffine(&prv.params.B.Affine_R)
  246. xRB.Z.One()
  247. xQB.FromAffine(&prv.params.B.Affine_Q)
  248. xQB.Z.One()
  249. xPB.FromAffine(&prv.params.B.Affine_P)
  250. xPB.Z.One()
  251. // Find isogeny kernel
  252. tmp.A.Zero()
  253. tmp.C.One()
  254. xR = p751.RightToLeftLadder(&tmp, &xPA, &xQA, &xRA, prv.params.A.SecretBitLen, prv.Scalar)
  255. // Reset params object and travers isogeny tree
  256. tmp.A.Zero()
  257. tmp.C.One()
  258. traverseTreePublicKeyA(&tmp, &xR, &xPB, &xQB, &xRB, pub)
  259. // Secret isogeny
  260. phi.GenerateCurve(&xR)
  261. xPA = phi.EvaluatePoint(&xPB)
  262. xQA = phi.EvaluatePoint(&xQB)
  263. xRA = phi.EvaluatePoint(&xRB)
  264. p751.ExtensionFieldBatch3Inv(&xPA.Z, &xQA.Z, &xRA.Z, &invZP, &invZQ, &invZR)
  265. pub.affine_xP.Mul(&xPA.X, &invZP)
  266. pub.affine_xQ.Mul(&xQA.X, &invZQ)
  267. pub.affine_xQmP.Mul(&xRA.X, &invZR)
  268. */
  269. return
  270. }
  271. // Generate a public key in the 3-torsion group
  272. func publicKeyGenB(prv *PrivateKey) (pub *PublicKey) {
  273. var xPB, xQB, xRB, xR p751.ProjectivePoint
  274. var xPA, xQA, xRA p751.ProjectivePoint
  275. var invZP, invZQ, invZR p751.ExtensionFieldElement
  276. var tmp p751.ProjectiveCurveParameters
  277. var phi = p751.NewIsogeny3()
  278. pub = NewPublicKey(prv.params.Id, prv.keyVariant)
  279. // Load points for A
  280. xPA.FromAffine(&prv.params.A.Affine_P)
  281. xPA.Z.One()
  282. xQA.FromAffine(&prv.params.A.Affine_Q)
  283. xQA.Z.One()
  284. xRA.FromAffine(&prv.params.A.Affine_R)
  285. xRA.Z.One()
  286. // Load points for B
  287. xRB.FromAffine(&prv.params.B.Affine_R)
  288. xRB.Z.One()
  289. xQB.FromAffine(&prv.params.B.Affine_Q)
  290. xQB.Z.One()
  291. xPB.FromAffine(&prv.params.B.Affine_P)
  292. xPB.Z.One()
  293. tmp.A.Zero()
  294. tmp.C.One()
  295. xR = p751.RightToLeftLadder(&tmp, &xPB, &xQB, &xRB, prv.params.B.SecretBitLen, prv.Scalar)
  296. tmp.A.Zero()
  297. tmp.C.One()
  298. traverseTreePublicKeyB(&tmp, &xR, &xPA, &xQA, &xRA, pub)
  299. phi.GenerateCurve(&xR)
  300. xPB = phi.EvaluatePoint(&xPA)
  301. xQB = phi.EvaluatePoint(&xQA)
  302. xRB = phi.EvaluatePoint(&xRA)
  303. p751.ExtensionFieldBatch3Inv(&xPB.Z, &xQB.Z, &xRB.Z, &invZP, &invZQ, &invZR)
  304. pub.affine_xP.Mul(&xPB.X, &invZP)
  305. pub.affine_xQ.Mul(&xQB.X, &invZQ)
  306. pub.affine_xQmP.Mul(&xRB.X, &invZR)
  307. return
  308. }
  309. // -----------------------------------------------------------------------------
  310. // Key agreement functions
  311. //
  312. // Establishing shared keys in in 2-torsion group
  313. func deriveSecretA(prv *PrivateKey, pub *PublicKey) []byte {
  314. var sharedSecret = make([]byte, pub.params.SharedSecretSize)
  315. var cparam p751.ProjectiveCurveParameters
  316. var xP, xQ, xQmP p751.ProjectivePoint
  317. var xR p751.ProjectivePoint
  318. var phi = p751.NewIsogeny4()
  319. // Recover curve coefficients
  320. cparam.RecoverCoordinateA(&pub.affine_xP, &pub.affine_xQ, &pub.affine_xQmP)
  321. cparam.C.One()
  322. // Find kernel of the morphism
  323. xP.FromAffine(&pub.affine_xP)
  324. xQ.FromAffine(&pub.affine_xQ)
  325. xQmP.FromAffine(&pub.affine_xQmP)
  326. xR = p751.RightToLeftLadder(&cparam, &xP, &xQ, &xQmP, pub.params.A.SecretBitLen, prv.Scalar)
  327. // Traverse isogeny tree
  328. traverseTreeSharedKeyA(&cparam, &xR, pub)
  329. // Calculate j-invariant on isogeneus curve
  330. c := phi.GenerateCurve(&xR)
  331. cparam.RecoverCurveCoefficients4(&c)
  332. cparam.Jinvariant(sharedSecret)
  333. return sharedSecret
  334. }
  335. // Establishing shared keys in in 3-torsion group
  336. func deriveSecretB(prv *PrivateKey, pub *PublicKey) []byte {
  337. var sharedSecret = make([]byte, pub.params.SharedSecretSize)
  338. var xP, xQ, xQmP p751.ProjectivePoint
  339. var xR p751.ProjectivePoint
  340. var cparam p751.ProjectiveCurveParameters
  341. var phi = p751.NewIsogeny3()
  342. // Recover curve coefficients
  343. cparam.RecoverCoordinateA(&pub.affine_xP, &pub.affine_xQ, &pub.affine_xQmP)
  344. cparam.C.One()
  345. // Find kernel of the morphism
  346. xP.FromAffine(&pub.affine_xP)
  347. xQ.FromAffine(&pub.affine_xQ)
  348. xQmP.FromAffine(&pub.affine_xQmP)
  349. xR = p751.RightToLeftLadder(&cparam, &xP, &xQ, &xQmP, pub.params.B.SecretBitLen, prv.Scalar)
  350. // Traverse isogeny tree
  351. traverseTreeSharedKeyB(&cparam, &xR, pub)
  352. // Calculate j-invariant on isogeneus curve
  353. c := phi.GenerateCurve(&xR)
  354. cparam.RecoverCurveCoefficients3(&c)
  355. cparam.Jinvariant(sharedSecret)
  356. return sharedSecret
  357. }