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.
 
 
 
 
 

140 regels
3.2 KiB

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