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.
 
 
 
 
 

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