ed25519ll_djbec.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. # Ported to Python 3 (added floor division) from ed25519ll package:
  2. # https://pypi.org/project/ed25519ll/
  3. # This module is adapted from that package's pure-Python fallback
  4. # implementation. All functions and vars not required by MMGen have
  5. # been removed.
  6. #
  7. # ed25519ll, a low-level ctypes wrapper for Ed25519 digital signatures by
  8. # Daniel Holth <dholth@fastmail.fm> - http://bitbucket.org/dholth/ed25519ll/
  9. # This wrapper also contains a reasonably performant pure-Python fallback.
  10. # Unlike the reference implementation, the Python implementation does not
  11. # contain protection against timing attacks.
  12. #
  13. # Ed25519 digital signatures
  14. # Based on http://ed25519.cr.yp.to/python/ed25519.py
  15. # See also http://ed25519.cr.yp.to/software.html
  16. # Adapted by Ron Garret
  17. # Sped up considerably using coordinate transforms found on:
  18. # http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
  19. # Specifically add-2008-hwcd-4 and dbl-2008-hwcd
  20. q = 2**255 - 19
  21. def expmod(b,e,m):
  22. if e == 0: return 1
  23. t = expmod(b,e//2,m)**2 % m
  24. if e & 1: t = (t*b) % m
  25. return t
  26. # Can probably get some extra speedup here by replacing this with
  27. # an extended-euclidean, but performance seems OK without that
  28. def inv(x):
  29. return expmod(x,q-2,q)
  30. # Faster (!) version based on:
  31. # http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
  32. def xpt_add(pt1, pt2):
  33. (X1, Y1, Z1, T1) = pt1
  34. (X2, Y2, Z2, T2) = pt2
  35. A = ((Y1-X1)*(Y2+X2)) % q
  36. B = ((Y1+X1)*(Y2-X2)) % q
  37. C = (Z1*2*T2) % q
  38. D = (T1*2*Z2) % q
  39. E = (D+C) % q
  40. F = (B-A) % q
  41. G = (B+A) % q
  42. H = (D-C) % q
  43. X3 = (E*F) % q
  44. Y3 = (G*H) % q
  45. Z3 = (F*G) % q
  46. T3 = (E*H) % q
  47. return (X3, Y3, Z3, T3)
  48. def xpt_double (pt):
  49. (X1, Y1, Z1, _) = pt
  50. A = (X1*X1)
  51. B = (Y1*Y1)
  52. C = (2*Z1*Z1)
  53. D = (-A) % q
  54. J = (X1+Y1) % q
  55. E = (J*J-A-B) % q
  56. G = (D+B) % q
  57. F = (G-C) % q
  58. H = (D-B) % q
  59. X3 = (E*F) % q
  60. Y3 = (G*H) % q
  61. Z3 = (F*G) % q
  62. T3 = (E*H) % q
  63. return (X3, Y3, Z3, T3)
  64. def pt_xform (pt):
  65. (x, y) = pt
  66. return (x, y, 1, (x*y)%q)
  67. def pt_unxform (pt):
  68. (x, y, z, _) = pt
  69. return ((x*inv(z))%q, (y*inv(z))%q)
  70. def xpt_mult (pt, n):
  71. if n==0: return pt_xform((0,1))
  72. _ = xpt_double(xpt_mult(pt, n>>1))
  73. return xpt_add(_, pt) if n&1 else _
  74. def scalarmult(pt, e):
  75. return pt_unxform(xpt_mult(pt_xform(pt), e))