ed25519ll_djbec.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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: return 1
  27. t = expmod(b,e//2,m)**2 % m
  28. if e & 1: t = (t*b) % m
  29. return t
  30. # Can probably get some extra speedup here by replacing this with
  31. # an extended-euclidean, but performance seems OK without that
  32. def inv(x):
  33. return expmod(x,q-2,q)
  34. # Faster (!) version based on:
  35. # http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
  36. def xpt_add(pt1, pt2):
  37. (X1, Y1, Z1, T1) = pt1
  38. (X2, Y2, Z2, T2) = pt2
  39. A = ((Y1-X1)*(Y2+X2)) % q
  40. B = ((Y1+X1)*(Y2-X2)) % q
  41. C = (Z1*2*T2) % q
  42. D = (T1*2*Z2) % q
  43. E = (D+C) % q
  44. F = (B-A) % q
  45. G = (B+A) % q
  46. H = (D-C) % q
  47. X3 = (E*F) % q
  48. Y3 = (G*H) % q
  49. Z3 = (F*G) % q
  50. T3 = (E*H) % q
  51. return (X3, Y3, Z3, T3)
  52. def xpt_double (pt):
  53. (X1, Y1, Z1, _) = pt
  54. A = (X1*X1)
  55. B = (Y1*Y1)
  56. C = (2*Z1*Z1)
  57. D = (-A) % q
  58. J = (X1+Y1) % q
  59. E = (J*J-A-B) % q
  60. G = (D+B) % q
  61. F = (G-C) % q
  62. H = (D-B) % q
  63. X3 = (E*F) % q
  64. Y3 = (G*H) % q
  65. Z3 = (F*G) % q
  66. T3 = (E*H) % q
  67. return (X3, Y3, Z3, T3)
  68. def pt_xform (pt):
  69. (x, y) = pt
  70. return (x, y, 1, (x*y)%q)
  71. def pt_unxform (pt):
  72. (x, y, z, _) = pt
  73. return ((x*inv(z))%q, (y*inv(z))%q)
  74. def xpt_mult (pt, n):
  75. if n==0: return pt_xform((0,1))
  76. _ = xpt_double(xpt_mult(pt, n>>1))
  77. return xpt_add(_, pt) if n&1 else _
  78. def scalarmult(pt, e):
  79. return pt_unxform(xpt_mult(pt_xform(pt), e))