ed25519ll_djbec.py 2.3 KB

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