-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathelgamal.py
94 lines (73 loc) · 2.05 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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created in 2021
@author: Stanislas MEZUREUX
Copyright (c) 2021 Stanislas MEZUREUX. All rights reserved.
"""
import random
NUMBITS = 1024
# q -> cyclic group order
# g -> cyclic group generator
# x -> prvate key
# (q, g, h) where h = g**x mod q -> private key
def gcd(a, b):
if a < b:
return gcd(b, a)
elif a%b == 0:
return b;
else:
return gcd(b, a%b)
# Miller-Rabin
# medium.com/@prudywsh/how-to-generate-big-prime-numbers-miller-rabin-49e6e6af32fb
def is_prime(n, k=128):
if n == 2 or n == 3:
return True
if n <= 1 or n % 2 == 0:
return False
s = 0
r = n - 1
while r & 1 == 0:
s += 1
r //= 2
for _ in range(k):
a = random.randrange(2, n - 1)
x = pow(a, r, n)
if x != 1 and x != n - 1:
j = 1
while j < s and x != n - 1:
x = pow(x, 2, n)
if x == 1:
return False
j += 1
if x != n - 1:
return False
return True
def generate_prime_candidate(length):
p = random.getrandbits(length)
p |= (1 << length - 1) | 1
return p
def generate_prime_number(length=1024):
p = 4
while not is_prime(p, 128):
p = generate_prime_candidate(length)
return p
def keygen():
q = generate_prime_number(NUMBITS)
g = random.randint(2, q)
x = random.randint(2**(NUMBITS-1), q)
return (x, {'q': q, 'g': g, 'h': pow(g, x, q)})
def encrypt(n, pk):
q, g, h = pk['q'], pk['g'], pk['h']
r = random.randint(2**(NUMBITS-1),q)
return {'c1': pow(g, r, q), 'c2': n*pow(h, r, q)}
def decrypt(n, x, pk):
return (n['c2']*pow(n['c1'], -x, pk['q']))%pk['q']
def multiply(n1, n2):
n1c1, n1c2 = n1['c1'], n1['c2']
n2c1, n2c2 = n2['c1'], n2['c2']
return {'c1': n1c1*n2c1, 'c2': n1c2*n2c2}
def is_equal(n1, n2, sk, pk):
d = {'c1': n1['c1']*pow(n2['c1'], -1, pk['q']),
'c2': n1['c2']*pow(n2['c2'], -1, pk['q'])}
return decrypt(d, sk, pk) == 1