slow_ed25519.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. # This is the ed25519 implementation from
  2. # http://ed25519.cr.yp.to/python/ed25519.py .
  3. # It is in the public domain.
  4. #
  5. # It isn't constant-time. Don't use it except for testing.
  6. import hashlib
  7. b = 256
  8. q = 2**255 - 19
  9. l = 2**252 + 27742317777372353535851937790883648493
  10. def H(m):
  11. return hashlib.sha512(m).digest()
  12. def expmod(b,e,m):
  13. if e == 0: return 1
  14. t = expmod(b,e/2,m)**2 % m
  15. if e & 1: t = (t*b) % m
  16. return t
  17. def inv(x):
  18. return expmod(x,q-2,q)
  19. d = -121665 * inv(121666)
  20. I = expmod(2,(q-1)/4,q)
  21. def xrecover(y):
  22. xx = (y*y-1) * inv(d*y*y+1)
  23. x = expmod(xx,(q+3)/8,q)
  24. if (x*x - xx) % q != 0: x = (x*I) % q
  25. if x % 2 != 0: x = q-x
  26. return x
  27. By = 4 * inv(5)
  28. Bx = xrecover(By)
  29. B = [Bx % q,By % q]
  30. def edwards(P,Q):
  31. x1 = P[0]
  32. y1 = P[1]
  33. x2 = Q[0]
  34. y2 = Q[1]
  35. x3 = (x1*y2+x2*y1) * inv(1+d*x1*x2*y1*y2)
  36. y3 = (y1*y2+x1*x2) * inv(1-d*x1*x2*y1*y2)
  37. return [x3 % q,y3 % q]
  38. def scalarmult(P,e):
  39. if e == 0: return [0,1]
  40. Q = scalarmult(P,e/2)
  41. Q = edwards(Q,Q)
  42. if e & 1: Q = edwards(Q,P)
  43. return Q
  44. def encodeint(y):
  45. bits = [(y >> i) & 1 for i in range(b)]
  46. return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)])
  47. def encodepoint(P):
  48. x = P[0]
  49. y = P[1]
  50. bits = [(y >> i) & 1 for i in range(b - 1)] + [x & 1]
  51. return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)])
  52. def bit(h,i):
  53. return (ord(h[i/8]) >> (i%8)) & 1
  54. def publickey(sk):
  55. h = H(sk)
  56. a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
  57. A = scalarmult(B,a)
  58. return encodepoint(A)
  59. def Hint(m):
  60. h = H(m)
  61. return sum(2**i * bit(h,i) for i in range(2*b))
  62. def signature(m,sk,pk):
  63. h = H(sk)
  64. a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
  65. r = Hint(''.join([h[i] for i in range(b/8,b/4)]) + m)
  66. R = scalarmult(B,r)
  67. S = (r + Hint(encodepoint(R) + pk + m) * a) % l
  68. return encodepoint(R) + encodeint(S)
  69. def isoncurve(P):
  70. x = P[0]
  71. y = P[1]
  72. return (-x*x + y*y - 1 - d*x*x*y*y) % q == 0
  73. def decodeint(s):
  74. return sum(2**i * bit(s,i) for i in range(0,b))
  75. def decodepoint(s):
  76. y = sum(2**i * bit(s,i) for i in range(0,b-1))
  77. x = xrecover(y)
  78. if x & 1 != bit(s,b-1): x = q-x
  79. P = [x,y]
  80. if not isoncurve(P): raise Exception("decoding point that is not on curve")
  81. return P
  82. def checkvalid(s,m,pk):
  83. if len(s) != b/4: raise Exception("signature length is wrong")
  84. if len(pk) != b/8: raise Exception("public-key length is wrong")
  85. R = decodepoint(s[0:b/8])
  86. A = decodepoint(pk)
  87. S = decodeint(s[b/8:b/4])
  88. h = Hint(encodepoint(R) + pk + m)
  89. if scalarmult(B,S) != edwards(R,scalarmult(A,h)):
  90. raise Exception("signature does not pass verification")