This repository has been archived by the owner on Mar 24, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 259
/
example.py
140 lines (123 loc) · 3.18 KB
/
example.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
#!/usr/bin/env python2.7
from Crypto.Util.number import bytes_to_long, inverse, long_to_bytes
from Crypto.Random.random import randint
class PublicKey:
def __init__(self, h, p, g, q):
self.h = h
self.p = p
self.g = g
self.q = q
class PrivateKey:
def __init__(self, x, p, g, q):
self.x = x
self.p = p
self.g = g
self.q = q
def _generate_key():
"""
Generate private-public key pair.
For security reasons, either p should be a safe prime or g should have a
prime subgroup order. Otherwise it is vulnerable to Short Subgroup Attack.
:Parameters: _None_
:Variables:
g : int/long
Base point for modular exponentiation.
p : int/long
Modulus for modular exponentiation. Should be a safe prime.
x : int/long
Receiver's private key, should be kept secret.
h : int/long
Receiver's public key
q : int/long
Order of group generated by p and equals p-1
:Return: A tuple containing a Public Key object (class `PublicKey`) and
a Private Key object (class `PrivateKey`)
"""
# Assigning the largest 1024-bit safe prime as p
p = (1 << 1024) - 1093337
x = randint(2, p-2)
g = 7
q = p - 1
h = pow(g, x, p)
pubkey = PublicKey(h, p, g, q)
privkey = PrivateKey(x, p, g, q)
return (pubkey, privkey)
def _encrypt(message, pubkey):
"""
Encrypt message using ElGamal encryption system
:Parameters:
message : str
plaintext to be encrypted
pubkey : instance of `PublicKey` class
Alice's public key parameters used for encryption
:Variables:
g : int/long
Base point for modular exponentiation.
p : int/long
Modulus for modular exponentiation. Should be a safe prime.
h : int/long
Receiver's public key
q : int/long
Order of group generated by p and equals p-1
y : int/long
Ephemeral key generated by the sender
c1, c2: int/long
Ciphertext pair
s : int/long
Shared secret
:Return:
A tuple containing ciphertext pair c1, c2
"""
h = pubkey.h
p = pubkey.p
g = pubkey.g
q = pubkey.q
m = bytes_to_long(message)
# Generating ephemeral key: `y`
y = randint(2, p-2)
c1 = pow(g, y, p)
# Computing the shared secret: `s`
s = pow(h, y, p)
c2 = (m*s) % p
return (c1, c2)
def _decrypt(ciphertext, privkey):
"""
Decrypt ciphertext using ElGamal Encryption System
:Parameters:
ciphertext : int/long tuple
Ciphertext of ElGamal encrypted plaintext
privkey : instance of `PrivateKey` class
Receiver's private key used for decryption
:Variables:
g : int/long
Base point for modular exponentiation.
p : int/long
Modulus for modular exponentiation. Should be a safe prime.
q : int/long
Order of group generated by p and equals p-1
c1, c2: int/long
Ciphertext pair
x : int/long
Receiver's private key, should be kept secret.
s : int/long
Shared secret
"""
c1, c2 = ciphertext
g = privkey.g
p = privkey.p
x = privkey.x
s = pow(c1, x, p)
m = (c2*inverse(s, p)) % p
return m
if __name__ == "__main__":
from os import urandom
pubkey, privkey = _generate_key()
for i in range(100):
message = chr(1) + urandom(16)
ct = _encrypt(message, pubkey)
try:
assert long_to_bytes(_decrypt(ct, privkey)) == message
except:
print "[-] Something's wrong! Check the implementation!"
import sys
sys.exit()