-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathDSA.py
121 lines (103 loc) · 2.66 KB
/
DSA.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
from random import getrandbits
from math import sqrt
from sys import exit
from gmpy2 import is_prime # miller-rabin primality test
from gmpy2 import powmod # (x ** y) mod m
from sys import stdin
N = 1024
L = 160
# z^-1 mod a
def inverse(z,a):
if z > 0 and z < a and a > 0:
i = a
j = z
y1 = 1
y2 = 0
while j > 0:
q = i/j
r = i-j*q
y = y2 - y1*q
i, j = j, r
y2, y1 = y1, y
if i == 1:
return y2 % a
raise Exception('Inverse Error')
# Per-Message Secret Number generator
def number_gen(p,q,g):
c = getrandbits(N+64)
k = (c % (q-1))+1
try:
k_ = inverse(k,q)
return (k,k_)
except 'Inverse Error':
return number_gen(p,q,g)
# Sign opertation
def sign((p,q,g), H, (x, y)):
k,k_ = number_gen(p,q,g)
r = powmod(g,k,p) % q
z = long(H, 16)
s = (k_*(z+x*r)) % q
return (r, s)
# Verify operation
def verify((p,q,g), H, y, (r,s)):
if 0 < r and r < q and 0 < s and s < q:
w = inverse(s, q)
z = long(H, 16)
u1 = (z*w) % q
u2 = (r*w) % q
v = ((powmod(g,u1,p) * powmod(y,u2,p)) % p) % q
return v == r
raise Exception('Verify Error')
def is_valid(p,q,g):
return ( is_prime(p) and is_prime(q)
and no_bits(p) == 1024 and no_bits(q) == 160
and (p-1) % q == 0 and powmod(g,q,p) == 1 and g > 1)
# number of bits
def no_bits(p):
return (len(bin(p))-2)
def range_(begin, stop):
i = begin
while i < stop:
yield i
i += 1
def group(list, n):
return zip(* [list[i::n] for i in range(n)])
# Generate a pair of keys
def gen_pair((p,q,g)):
c = getrandbits(N+64)
x = (c % (q-1)) + 1
y = powmod(g,x,p)
return (x,y)
if __name__=='__main__':
p = long(raw_input()[2:])
q = long(raw_input()[2:])
g = long(raw_input()[2:])
if not is_valid(p,q,g):
print 'invalid_group'
exit(-1)
print 'valid_group'
token = raw_input()
if token == 'genkey':
n = long(raw_input()[2:])
while n > 0:
(x,y) = gen_pair((p,q,g))
print "x=" + str(x)
print "y=" + str(y)
n -= 1
elif token == 'sign':
x = long(raw_input()[2:])
y = long(raw_input()[2:])
Ds = [l[2:-1] for l in stdin]
signs = [sign((p,q,g), d, (x,y)) for d in Ds]
for (r,s) in signs:
print 'r='+str(r)
print 's='+str(s)
elif token == 'verify':
y = long(raw_input()[2:])
tuples = group([l[2:-1] for l in stdin], 3) # tuples (D, r, s)
verifies = [verify((p,q,g), t[0], y, (long(t[1]), long(t[2]))) for t in tuples]
for v in verifies:
if v:
print 'signature_valid'
else:
print 'signature_invalid'