-
Notifications
You must be signed in to change notification settings - Fork 77
/
Lab01Code.py
272 lines (205 loc) · 7.38 KB
/
Lab01Code.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
#####################################################
# GA17 Privacy Enhancing Technologies -- Lab 01
#
# Basics of Petlib, encryption, signatures and
# an end-to-end encryption system.
#
# Run the tests through:
# $ py.test-2.7 -v Lab01Tests.py
###########################
# Group Members: TODO
###########################
#####################################################
# TASK 1 -- Ensure petlib is installed on the System
# and also pytest. Ensure the Lab Code can
# be imported.
import petlib
#####################################################
# TASK 2 -- Symmetric encryption using AES-GCM
# (Galois Counter Mode)
#
# Implement a encryption and decryption function
# that simply performs AES_GCM symmetric encryption
# and decryption using the functions in petlib.cipher.
from os import urandom
from petlib.cipher import Cipher
def encrypt_message(K, message):
""" Encrypt a message under a key K """
plaintext = message.encode("utf8")
## YOUR CODE HERE
return (iv, ciphertext, tag)
def decrypt_message(K, iv, ciphertext, tag):
""" Decrypt a cipher text under a key K
In case the decryption fails, throw an exception.
"""
## YOUR CODE HERE
return plain.encode("utf8")
#####################################################
# TASK 3 -- Understand Elliptic Curve Arithmetic
# - Test if a point is on a curve.
# - Implement Point addition.
# - Implement Point doubling.
# - Implement Scalar multiplication (double & add).
# - Implement Scalar multiplication (Montgomery ladder).
#
# MUST NOT USE ANY OF THE petlib.ec FUNCIONS. Only petlib.bn!
from petlib.bn import Bn
def is_point_on_curve(a, b, p, x, y):
"""
Check that a point (x, y) is on the curve defined by a,b and prime p.
Reminder: an Elliptic Curve on a prime field p is defined as:
y^2 = x^3 + ax + b (mod p)
(Weierstrass form)
Return True if point (x,y) is on curve, otherwise False.
By convention a (None, None) point represents "infinity".
"""
assert isinstance(a, Bn)
assert isinstance(b, Bn)
assert isinstance(p, Bn) and p > 0
assert (isinstance(x, Bn) and isinstance(y, Bn)) \
or (x == None and y == None)
if x == None and y == None:
return True
lhs = (y * y) % p
rhs = (x*x*x + a*x + b) % p
on_curve = (lhs == rhs)
return on_curve
def point_add(a, b, p, x0, y0, x1, y1):
"""Define the "addition" operation for 2 EC Points.
Reminder: (xr, yr) = (xq, yq) + (xp, yp)
is defined as:
lam = (yq - yp) * (xq - xp)^-1 (mod p)
xr = lam^2 - xp - xq (mod p)
yr = lam * (xp - xr) - yp (mod p)
Return the point resulting from the addition. Raises an Exception if the points are equal.
"""
# ADD YOUR CODE BELOW
xr, yr = None, None
return (xr, yr)
def point_double(a, b, p, x, y):
"""Define "doubling" an EC point.
A special case, when a point needs to be added to itself.
Reminder:
lam = (3 * xp ^ 2 + a) * (2 * yp) ^ -1 (mod p)
xr = lam ^ 2 - 2 * xp
yr = lam * (xp - xr) - yp (mod p)
Returns the point representing the double of the input (x, y).
"""
# ADD YOUR CODE BELOW
xr, yr = None, None
return xr, yr
def point_scalar_multiplication_double_and_add(a, b, p, x, y, scalar):
"""
Implement Point multiplication with a scalar:
r * (x, y) = (x, y) + ... + (x, y) (r times)
Reminder of Double and Multiply algorithm: r * P
Q = infinity
for i = 0 to num_bits(P)-1
if bit i of r == 1 then
Q = Q + P
P = 2 * P
return Q
"""
Q = (None, None)
P = (x, y)
for i in range(scalar.num_bits()):
pass ## ADD YOUR CODE HERE
return Q
def point_scalar_multiplication_montgomerry_ladder(a, b, p, x, y, scalar):
"""
Implement Point multiplication with a scalar:
r * (x, y) = (x, y) + ... + (x, y) (r times)
Reminder of Double and Multiply algorithm: r * P
R0 = infinity
R1 = P
for i in num_bits(P)-1 to zero:
if di = 0:
R1 = R0 + R1
R0 = 2R0
else
R0 = R0 + R1
R1 = 2 R1
return R0
"""
R0 = (None, None)
R1 = (x, y)
for i in reversed(range(0,scalar.num_bits())):
pass ## ADD YOUR CODE HERE
return R0
#####################################################
# TASK 4 -- Standard ECDSA signatures
#
# - Implement a key / param generation
# - Implement ECDSA signature using petlib.ecdsa
# - Implement ECDSA signature verification
# using petlib.ecdsa
from hashlib import sha256
from petlib.ec import EcGroup
from petlib.ecdsa import do_ecdsa_sign, do_ecdsa_verify
def ecdsa_key_gen():
""" Returns an EC group, a random private key for signing
and the corresponding public key for verification"""
G = EcGroup()
priv_sign = G.order().random()
pub_verify = priv_sign * G.generator()
return (G, priv_sign, pub_verify)
def ecdsa_sign(G, priv_sign, message):
""" Sign the SHA256 digest of the message using ECDSA and return a signature """
plaintext = message.encode("utf8")
## YOUR CODE HERE
return sig
def ecdsa_verify(G, pub_verify, message, sig):
""" Verify the ECDSA signature on the message """
plaintext = message.encode("utf8")
## YOUR CODE HERE
return res
#####################################################
# TASK 5 -- Diffie-Hellman Key Exchange and Derivation
# - use Bob's public key to derive a shared key.
# - Use Bob's public key to encrypt a message.
# - Use Bob's private key to decrypt the message.
#
# NOTE:
def dh_get_key():
""" Generate a DH key pair """
G = EcGroup()
priv_dec = G.order().random()
pub_enc = priv_dec * G.generator()
return (G, priv_dec, pub_enc)
def dh_encrypt(pub, message, aliceSig = None):
""" Assume you know the public key of someone else (Bob),
and wish to Encrypt a message for them.
- Generate a fresh DH key for this message.
- Derive a fresh shared key.
- Use the shared key to AES_GCM encrypt the message.
- Optionally: sign the message with Alice's key.
"""
## YOUR CODE HERE
pass
def dh_decrypt(priv, ciphertext, aliceVer = None):
""" Decrypt a received message encrypted using your public key,
of which the private key is provided. Optionally verify
the message came from Alice using her verification key."""
## YOUR CODE HERE
pass
## NOTE: populate those (or more) tests
# ensure they run using the "py.test filename" command.
# What is your test coverage? Where is it missing cases?
# $ py.test-2.7 --cov-report html --cov Lab01Code Lab01Code.py
def test_encrypt():
assert False
def test_decrypt():
assert False
def test_fails():
assert False
#####################################################
# TASK 6 -- Time EC scalar multiplication
# Open Task.
#
# - Time your implementations of scalar multiplication
# (use time.clock() for measurements)for different
# scalar sizes)
# - Print reports on timing dependencies on secrets.
# - Fix one implementation to not leak information.
def time_scalar_mul():
pass