-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimple_rsa.py
347 lines (254 loc) · 8.5 KB
/
simple_rsa.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
import random
# Function to get random bit
def random_bit():
rand_num = random.randint(0,4294967295) # Random number between 0 and 2^32-1
bin_rand_num = format(rand_num, '032b') # 32-bit binary representation of Random number
lsb_bit = rand_num & 1 # LSB bit of Random number
return lsb_bit,bin_rand_num,rand_num
# Function to get 7-bit random number
def random_num_7bit():
rand_num = 1 # b_7
rand_num = rand_num << 1 # Bit shift by 1 to left
for i in range(5,0,-1):
rand_bit,_,_ = random_bit()
rand_num = rand_num + rand_bit #Adding new random bit to final random number
rand_num = rand_num << 1 # Bit shift by 1 to left
rand_num = rand_num + 1 #b_0
return rand_num
# Function to get 'a' for Miller-Rabin
def get_a(n):
return random.randint(1,n-1)
# Fast Exponentiation
def fast_exponentiation(n,a,x):
k = len(bin(x))-3
y = 1
j=2
for i in range(k,-1,-1):
xi = bin(x)[j] # Getting xi binary number
y = (y*y)%n
if xi=='1':
y = (y*a)%n
j+=1
return y
# Miller-Rabin Primality Testing
def primality_testing(n,a):
x = n-1
k = len(bin(x))-3
y = 1
j=2
for i in range(k,-1,-1):
z = y
xi = bin(x)[j] # Getting xi binary number
y = (y*y)%n
if y==1 and z!=1 and z!=n-1:
# Bad Square Root: n is not prime
return False
if xi=='1':
y = (y*a)%n
j+=1
if y!=1:
# Bad final value
return False
else:
return True
# Function to check if Prime using 20 rounds of Miller-Rabin
def is_prime(n):
for i in range(20):
a = get_a(n)
if not primality_testing(n,a):
# It is not Prime if it fails Miller-Rabin Primality Test
return False
# It is Prime if it passes for 20 a's
return True
# Extended Euclidean Algorithm to get Multiplicative Inverse and GCD
def extended_euclidean_algorithm(bigger_num, smaller_num):
ri = bigger_num
ri_1 = smaller_num
ri_2 = -1
qi = -1
qi_1 = -1
qi_2 = -1
si = -1
si_1 = -1
si_2 = -1
ti = -1
ti_1 = -1
ti_2 = -1
i = 1
while True:
if i == 1:
si_2 = 1
si = 1
ti_2 = 0
ti = 0
elif i == 2:
qi_1 = qi
si_1 = 0
si = 0
ti_1 = 1
ti = 1
else:
qi_2 = qi_1
qi_1 = qi
si = si_2 - (qi_2*si_1)
si_2 = si_1
si_1 = si
ti = ti_2 - (qi_2*ti_1)
ti_2 = ti_1
ti_1 = ti
if ri_1 == 0:
found_mult_inverse = False
if ri==1:
found_mult_inverse = True
while ti < 0: # Normalizing Multiplicative Inverse
ti = ti + bigger_num
return ti,ri,found_mult_inverse #Return (Multiplicative Inverse, GCD, Yes/No Multiplicative Inverse)
qi = int(ri/ri_1)
ri_2 = ri%ri_1
i+=1
ri = ri_1
ri_1 = ri_2
# Function to generate RSA Keys. Public Key: (n,e) ; Private Key: (n,d)
def generate_rsa_keys():
found_e = False
while not found_e: # In the rare case that an e was not found
#Calculating p and q
p = -1
q = -1
#Assigning p
while True:
n = random_num_7bit()
if is_prime(n):
p = n
break
#Assigning q
while True:
n = random_num_7bit()
if is_prime(n):
q = n
if q != p: #Checking that p and q are not equal
break
#Calculating n
n = p*q
#Calculating phi(n)
phi_n = (p-1)*(q-1)
e = 3 #Starting to check with e=3
d = -1
found_mult_inverse = False
while (not found_mult_inverse) and e < phi_n:
mult_inv,gcd,found_mult_inverse = extended_euclidean_algorithm(phi_n,e)
if not found_mult_inverse:
e+=1
else: # Found Multiplicative Inverse as GCD = 1
found_e = True
d = mult_inv
return p,q,n,e,d
# XOR between two bytes of data
def byte_xor(a,b):
s0 = str(int(a[0])^int(b[0]))
s1 = str(int(a[1])^int(b[1]))
s2 = str(int(a[2])^int(b[2]))
s3 = str(int(a[3])^int(b[3]))
s4 = str(int(a[4])^int(b[4]))
s5 = str(int(a[5])^int(b[5]))
s6 = str(int(a[6])^int(b[6]))
s7 = str(int(a[7])^int(b[7]))
return s0 + s1 + s2 + s3 + s4 + s5 + s6 + s7
# Simple hash function that XOR's byte-by-byte and returns respective int value
def hash_simple(bit_string):
byte_list = []
for i in range(0,len(bit_string),8):
byte_list.append(bit_string[i:i+8])
while len(byte_list) > 1:
byte_list[1] = byte_xor(byte_list[0],byte_list[1])
byte_list = byte_list[1:]
return int(byte_list[0], 2)
# Decrypting or Signing 'h' with Private Key (n,d)
def d_RSA(n,d,h):
return fast_exponentiation(n,h,d)
# Encrypting or Verifying 'h' with Public Key (n,e)
def e_RSA(n,e,h):
return fast_exponentiation(n,h,e)
def main():
# Generating Alice's RSA Keys
print("Generating Alice's RSA Keys")
p_Alice,q_Alice,n_Alice,e_Alice,d_Alice = generate_rsa_keys()
print("p = "+str(p_Alice)+", q = "+str(q_Alice)+", n = "+str(n_Alice)+", e = "+str(e_Alice)+", d = "+str(d_Alice))
print("p = "+format(p_Alice, '032b'))
print("q = "+format(q_Alice, '032b'))
print("n = "+format(n_Alice, '032b'))
print("e = "+format(e_Alice, '032b'))
print("d = "+format(d_Alice, '032b'))
# Empty Line
print()
# Generating Trent's Keys
print("Generating Trent's RSA Keys")
p_Trent,q_Trent,n_Trent,e_Trent,d_Trent = generate_rsa_keys()
print("p = "+str(p_Trent)+", q = "+str(q_Trent)+", n = "+str(n_Trent)+", e = "+str(e_Trent)+", d = "+str(d_Trent))
print("p = "+format(p_Trent, '032b'))
print("q = "+format(q_Trent, '032b'))
print("n = "+format(n_Trent, '032b'))
print("e = "+format(e_Trent, '032b'))
print("d = "+format(d_Trent, '032b'))
# Empty Line
print()
print()
print()
# Creating Alice's Digital Certificate signed by Trent
print("Creating Alice's Digital Certificate signed by Trent:")
print("--------------------------------------------------------")
print()
# Using The representation for 'Alice' = 32(Space),65(A),108(l),105(i),99(c),101(e)
Alice = "001000000100000101101100011010010110001101100101"
bytes_1_6 = Alice
bytes_7_10 = format(n_Alice, '032b')
bytes_11_14 = format(e_Alice, '032b')
r = bytes_1_6 +bytes_7_10 + bytes_11_14
h_r = hash_simple(r)
s = d_RSA(n_Trent,d_Trent,h_r) # Signing with Trent's Private Key (nt,dt)
print("Alice's Digital Certificate signed by Trent")
print("r = "+r)
print("h(r) = "+format(h_r, '032b'))
print("s = "+format(s, '032b'))
# Empty Line
print()
print("Integer Representation of Alice's Digital Certificate signed by Trent")
print("h(r) = "+str(h_r)+", s = "+str(s))
# Empty Line
print()
print()
print()
# Authentication of Alice by Bob
print("Authentication of Alice by Bob:")
print("---------------------------------------------")
print()
# Generating common u among Alice and Bob
print("Generating common u among Alice and Bob")
k = len(bin(n_Alice)) - 3
# Generating u which is cooperatively picked by Alice and Bob
u = '1' # (k-1)th u
for i in range(k-2):
rand_bit,_,_ = random_bit()
u = u+str(rand_bit)
u = u+'1' # 0th u
u = int(u, 2) #Converting from binary string to binary int
h_u = hash_simple(format(u, '032b')) # Calculating h(u)
print("k = "+str(k)+", u = "+str(u)+", h(u) = "+str(h_u))
# Printing binary representatioin of u
print("Binary representation of u and h(u)")
print("u = ", format(u, '032b'))
print("h(u) = ", format(h_u, '032b'))
# Empty Line
print()
# Authentication of Alice by Bob
print("Alice signing shared h(u)")
v = d_RSA(n_Alice,d_Alice,h_u) # Alice signing/decrypting h(u)
print("u = "+str(u)+", h(u) = "+str(h_u)+", v = "+str(v))
print()
print("Bob authenticating Alice")
Ev = e_RSA(n_Alice,e_Alice,v) # Bob verifying Ev is equal to h(u) to authenticate Alice
print("h(u) = "+str(h_u)+", v = "+str(v)+", Ev = "+str(Ev))
print("Ev = h(u)")
print("Alice authenticated by Bob!!")
if __name__ == "__main__":
main()