You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

129 lines
2.6 KiB

  1. # This is as sketch of how to decaffeinate Curve25519
  2. F = GF(2^255-19)
  3. d = -121665
  4. M = EllipticCurve(F,[0,2-4*d,0,1,0])
  5. sqrtN1 = sqrt(F(-1))
  6. def maybe(): return randint(0,1)
  7. def qpositive(x):
  8. return int(x) <= (2^255-19-1)/2
  9. def M_to_E(P):
  10. # P must be even
  11. (x,y) = P.xy()
  12. assert x.is_square()
  13. s = sqrt(x)
  14. if s == 0: t = 1
  15. else: t = y/s
  16. X,Y = 2*s / (1+s^2), (1-s^2) / t
  17. if maybe(): X,Y = -X,-Y
  18. if maybe(): X,Y = Y,-X
  19. # OK, have point in ed
  20. return X,Y
  21. def decaf_encode_from_E(X,Y):
  22. assert X^2 + Y^2 == 1 + d*X^2*Y^2
  23. if not qpositive(X*Y): X,Y = Y,-X
  24. assert qpositive(X*Y)
  25. assert (1-X^2).is_square()
  26. sx = sqrt(1-X^2)
  27. tos = -2*sx/X/Y
  28. if not qpositive(tos): sx = -sx
  29. s = (1 + sx) / X
  30. if not qpositive(s): s = -s
  31. return s
  32. def isqrt(x):
  33. ops = [(1,2),(1,2),(3,1),(6,0),(1,2),(12,1),(25,1),(25,1),(50,0),(125,0),(2,2),(1,2)]
  34. st = [x,x,x]
  35. for i,(sh,add) in enumerate(ops):
  36. od = i&1
  37. st[od] = st[od^^1]^(2^sh)*st[add]
  38. # assert st[2] == x^(2^252-3)
  39. assert st[1] == 1 or st[1] == -1
  40. if st[1] == 1: return st[0]
  41. else: return st[0] * sqrtN1
  42. def decaf_encode_from_E_c(X,Y):
  43. Z = F.random_element()
  44. T = X*Y*Z
  45. X = X*Z
  46. Y = Y*Z
  47. assert X^2 + Y^2 == Z^2 + d*T^2
  48. # Precompute
  49. sd = sqrt(F(1-d))
  50. zx = Z^2-X^2
  51. TZ = T*Z
  52. assert zx.is_square
  53. ooAll = isqrt(zx*TZ^2)
  54. osx = ooAll * TZ
  55. ooTZ = ooAll * zx * osx
  56. floop = qpositive(T^2 * ooTZ)
  57. if floop:
  58. frob = zx * ooTZ
  59. else:
  60. frob = sd
  61. Y = -X
  62. osx *= frob
  63. if qpositive(-2*osx*Z) != floop: osx = -osx
  64. s = Y*(ooTZ*Z + osx)
  65. if not qpositive(s): s = -s
  66. return s
  67. def is_rotation((X,Y),(x,y)):
  68. return x*Y == X*y or x*X == -y*Y
  69. def decaf_decode_to_E(s):
  70. assert qpositive(s)
  71. t = sqrt(s^4 + (2-4*d)*s^2 + 1)
  72. if not qpositive(t/s): t = -t
  73. X,Y = 2*s / (1+s^2), (1-s^2) / t
  74. assert qpositive(X*Y)
  75. return X,Y
  76. def decaf_decode_to_E_c(s):
  77. assert qpositive(s)
  78. s2 = s^2
  79. s21 = 1+s2
  80. t2 = s21^2 - 4*d*s2
  81. alt = s21*s
  82. the = isqrt(t2*alt^2)
  83. oot = the * alt
  84. the *= t2
  85. tos = the * s21
  86. X = 2 * (tos-the) * oot
  87. Y = (1-s2) * oot
  88. if not qpositive(tos): Y = -Y
  89. assert qpositive(X*Y)
  90. return X,Y
  91. def test():
  92. P = 2*M.random_point()
  93. X,Y = M_to_E(P)
  94. s = decaf_encode_from_E(X,Y)
  95. assert s == decaf_encode_from_E_c(X,Y)
  96. XX,YY = decaf_decode_to_E(s)
  97. XX2,YY2 = decaf_decode_to_E_c(s)
  98. assert is_rotation((X,Y),(XX,YY))
  99. assert is_rotation((X,Y),(XX2,YY2))