-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathelgamal.py
103 lines (83 loc) · 2.12 KB
/
elgamal.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
import random
from copy import deepcopy
def mod_pow(a, n, m):
a = a % m
result = 1
while n > 0:
if n % 2 == 1:
result = (result * a) % m
a = (a * a) % m
n = n // 2
return result
def extended_gcd(a, b):
if b == 0:
return (a, 1, 0)
d, m, n = extended_gcd(b, a % b)
return (d, n, m - a // b * n)
def mod_inv(a, x):
d, m, n = extended_gcd(a, x)
if d != 1:
print("Vrednosti a i x nisu uzajamno proste!")
else:
return m % x
def miller_rabin(n, k):
if n <= 3:
if n == 1:
return False
return True
d = n - 1
r = 0
while d % 2 == 0:
r = r + 1
d = d // 2
for i in range(k):
a = random.randrange(2, n - 1)
x = mod_pow(a, d, n)
if x == 1 or x == n - 1:
continue
witness = True
for j in range(r - 1):
x = mod_pow(x, 2, n)
if x == 1:
return False
if x == n - 1: # n - 1 = -1 (mod n)
witness = False
break
if witness:
return False
return True
def get_prime(limit, k = 20):
is_prime = False
while not is_prime:
n = random.randrange(limit)
is_prime = miller_rabin(n, k)
return n
class ElGamal:
def __init__(self, q, g):
self.q=q
self.g=g
self.pr=random.randrange(2, self.q)
self.pub=mod_pow(self.g, self.pr, self.q)
def encrypt(self, m, pub_key):
k=random.randrange(2, self.q)
g_k=mod_pow(self.g, k, self.q)
e=mod_pow(g_k, pub_key, self.q)
me=(m * e) % self.q
return (me, g_k)
def decrypt(self, me, g_k):
e=mod_pow(g_k, self.pr, self.q)
d=mod_inv(e, self.q)
m=(me*d)%self.q
return m
def main():
q=get_prime(2**256)
g=random.randrange(2, q)
A=ElGamal(q, g)
B=ElGamal(q, g)
m=123000
(me, g_k)=A.encrypt(m, B.pub)
md=B.decrypt(me, g_k)
print("Sifrovano: ", me)
print("Desifrovano: ", md)
if __name__=="__main__":
main()