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.
 
 
 
 
 

111 lines
3.3 KiB

  1. F = GF(2^255-19)
  2. dM = F(-121665)
  3. d = F(-121665/121666)
  4. ii = sqrt(F(-1))
  5. def lobit(x): return int(x) & 1
  6. def hibit(x): return lobit(2*x)
  7. magic = sqrt(F(-121666))
  8. if lobit(magic): magic = -magic
  9. def eddsa_to_decaf(x,y):
  10. """
  11. Converts an EdDSA point to a Decaf representation, in a manner compatible
  12. with libdecaf.
  13. The input point must be even.
  14. Note well! Decaf does not represent the cofactor information of a point.
  15. So e2d(d2e(s)) = s, but d2e(e2d(x,y)) might not be (x,y).
  16. """
  17. if x*y == 0: return 0 # This will happen anyway with straightforward square root trick
  18. if not is_square((1-y)/(1+y)): raise Exception("Unimplemented: odd point in eddsa_to_decaf")
  19. if hibit(magic/(x*y)): (x,y) = (ii*y,ii*x)
  20. if hibit(2*magic/x): y = -y
  21. s = sqrt((1-y)/(1+y))
  22. if hibit(s): s = -s
  23. return s
  24. def isqrt_trick(to_isr,to_inv):
  25. to_sqrt = to_isr*to_inv^2
  26. if to_sqrt == 0: return 0,0,0 # This happens automatically in C; just to avoid problems in SAGE
  27. if not is_square(to_sqrt): raise Exception("Not square in isqrt_trick!")
  28. tmp = 1/sqrt(to_sqrt)
  29. isr = tmp * to_inv
  30. inv = tmp * isr * to_isr
  31. assert isr^2 == 1/to_isr
  32. assert inv == 1/to_inv
  33. return isr, inv, tmp
  34. def eddsa_to_decaf_opt(x,y,z=None):
  35. """
  36. Optimized version of eddsa_to_decaf. Uses only one isqrt.
  37. There's probably some way to further optimize if you have a T-coord,
  38. but whatever.
  39. """
  40. if z is None:
  41. # Pretend that we're in projective
  42. z = F.random_element()
  43. x *= z
  44. y *= z
  45. isr,inv,tmp = isqrt_trick(z^2-y^2,x*y)
  46. minv = inv*magic*z
  47. rotate = hibit(minv*z)
  48. if rotate:
  49. isr = tmp*(z^2-y^2)*magic
  50. y = ii*x
  51. if hibit(2*minv*y) != rotate: y = -y
  52. s = (z-y) * isr
  53. if hibit(s): s = -s
  54. return s
  55. print [eddsa_to_decaf_opt(x,y) == eddsa_to_decaf(x,y) for _,_,_,_,y1,y2 in points for x,y in [decode(y1,y2)]]
  56. def decaf_to_eddsa(s):
  57. """
  58. Convert a Decaf representation to an EdDSA point, in a manner compatible
  59. with libdecaf.
  60. Note well! The Decaf representation of a point is canonical, but the EdDSA one
  61. is not, in that
  62. """
  63. if s == 0: return (0,1)
  64. if hibit(s): raise Exception("invalid: s has high bit")
  65. if not is_square(s^4 + (2-4*dM)*s^2 + 1): raise Exception("invalid: not on curve")
  66. t = sqrt(s^4 + (2-4*dM)*s^2 + 1)/s
  67. if hibit(t): t = -t
  68. y = (1-s^2)/(1+s^2)
  69. x = 2*magic/t
  70. if y == 0 or lobit(t/y): raise Exception("invalid: t/y has high bit")
  71. assert y^2 - x^2 == 1+d*x^2*y^2
  72. return (x,y)
  73. def decaf_to_eddsa_opt(s):
  74. """
  75. Convert a Decaf representation to an EdDSA point, in a manner compatible
  76. with libdecaf.
  77. """
  78. if s == 0: return (0,1)
  79. if hibit(s): raise Exception("invalid: s has high bit")
  80. if not is_square(s^4 + (2-4*dM)*s^2 + 1): raise Exception("invalid: not on curve")
  81. t = sqrt(s^4 + (2-4*dM)*s^2 + 1)/s
  82. if hibit(t): t = -t
  83. y = (1-s^2)/(1+s^2)
  84. x = 2*magic/t
  85. if y == 0 or lobit(t/y): raise Exception("invalid: t/y has high bit")
  86. assert y^2 - x^2 == 1+d*x^2*y^2
  87. return (x,y)
  88. print [s == eddsa_to_decaf(*decaf_to_eddsa(s)) for _,_,s,_,_,_ in points]
  89. print [s == eddsa_to_decaf_opt(*decaf_to_eddsa_opt(s)) for _,_,s,_,_,_ in points]