Merge remote-tracking branch 'tor-github/pr/392' into maint-0.2.9
[tor.git] / src / test / slow_ed25519.py
blobf44708b20073fe90c628aa180f1705a31d691ec9
1 # This is the ed25519 implementation from
2 # http://ed25519.cr.yp.to/python/ed25519.py .
3 # It is in the public domain.
5 # It isn't constant-time. Don't use it except for testing. Also, see
6 # warnings about how very slow it is. Only use this for generating
7 # test vectors, I'd suggest.
9 # Don't edit this file. Mess with ed25519_ref.py
11 import hashlib
13 b = 256
14 q = 2**255 - 19
15 l = 2**252 + 27742317777372353535851937790883648493
17 def H(m):
18 return hashlib.sha512(m).digest()
20 def expmod(b,e,m):
21 if e == 0: return 1
22 t = expmod(b,e/2,m)**2 % m
23 if e & 1: t = (t*b) % m
24 return t
26 def inv(x):
27 return expmod(x,q-2,q)
29 d = -121665 * inv(121666)
30 I = expmod(2,(q-1)/4,q)
32 def xrecover(y):
33 xx = (y*y-1) * inv(d*y*y+1)
34 x = expmod(xx,(q+3)/8,q)
35 if (x*x - xx) % q != 0: x = (x*I) % q
36 if x % 2 != 0: x = q-x
37 return x
39 By = 4 * inv(5)
40 Bx = xrecover(By)
41 B = [Bx % q,By % q]
43 def edwards(P,Q):
44 x1 = P[0]
45 y1 = P[1]
46 x2 = Q[0]
47 y2 = Q[1]
48 x3 = (x1*y2+x2*y1) * inv(1+d*x1*x2*y1*y2)
49 y3 = (y1*y2+x1*x2) * inv(1-d*x1*x2*y1*y2)
50 return [x3 % q,y3 % q]
52 def scalarmult(P,e):
53 if e == 0: return [0,1]
54 Q = scalarmult(P,e/2)
55 Q = edwards(Q,Q)
56 if e & 1: Q = edwards(Q,P)
57 return Q
59 def encodeint(y):
60 bits = [(y >> i) & 1 for i in range(b)]
61 return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)])
63 def encodepoint(P):
64 x = P[0]
65 y = P[1]
66 bits = [(y >> i) & 1 for i in range(b - 1)] + [x & 1]
67 return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)])
69 def bit(h,i):
70 return (ord(h[i/8]) >> (i%8)) & 1
72 def publickey(sk):
73 h = H(sk)
74 a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
75 A = scalarmult(B,a)
76 return encodepoint(A)
78 def Hint(m):
79 h = H(m)
80 return sum(2**i * bit(h,i) for i in range(2*b))
82 def signature(m,sk,pk):
83 h = H(sk)
84 a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
85 r = Hint(''.join([h[i] for i in range(b/8,b/4)]) + m)
86 R = scalarmult(B,r)
87 S = (r + Hint(encodepoint(R) + pk + m) * a) % l
88 return encodepoint(R) + encodeint(S)
90 def isoncurve(P):
91 x = P[0]
92 y = P[1]
93 return (-x*x + y*y - 1 - d*x*x*y*y) % q == 0
95 def decodeint(s):
96 return sum(2**i * bit(s,i) for i in range(0,b))
98 def decodepoint(s):
99 y = sum(2**i * bit(s,i) for i in range(0,b-1))
100 x = xrecover(y)
101 if x & 1 != bit(s,b-1): x = q-x
102 P = [x,y]
103 if not isoncurve(P): raise Exception("decoding point that is not on curve")
104 return P
106 def checkvalid(s,m,pk):
107 if len(s) != b/4: raise Exception("signature length is wrong")
108 if len(pk) != b/8: raise Exception("public-key length is wrong")
109 R = decodepoint(s[0:b/8])
110 A = decodepoint(pk)
111 S = decodeint(s[b/8:b/4])
112 h = Hint(encodepoint(R) + pk + m)
113 if scalarmult(B,S) != edwards(R,scalarmult(A,h)):
114 raise Exception("signature does not pass verification")