Skip to content

Commit f3545aa

Browse files
authored
Merge pull request #50 from web-push-libs/feat/49
feat: update public key calls
2 parents 1cf8af2 + a911320 commit f3545aa

File tree

2 files changed

+58
-29
lines changed

2 files changed

+58
-29
lines changed

python/http_ece/__init__.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
from cryptography.hazmat.primitives.ciphers import (
1010
Cipher, algorithms, modes
1111
)
12+
from cryptography.hazmat.primitives.serialization import (
13+
Encoding, PublicFormat
14+
)
1215
from cryptography.hazmat.primitives.asymmetric import ec
1316

1417
MAX_RECORD_SIZE = pow(2, 31) - 1
@@ -24,11 +27,13 @@
2427
"aesgcm128": {"pad": 1},
2528
}
2629

30+
2731
class ECEException(Exception):
2832
"""Exception for ECE encryption functions"""
2933
def __init__(self, message):
3034
self.message = message
3135

36+
3237
def derive_key(mode, version, salt, key,
3338
private_key, dh, auth_secret,
3439
keyid, keylabel="P-256"):
@@ -64,15 +69,20 @@ def build_info(base, info_context):
6469
def derive_dh(mode, version, private_key, dh, keylabel):
6570
def length_prefix(key):
6671
return struct.pack("!H", len(key)) + key
67-
6872
if isinstance(dh, ec.EllipticCurvePublicKey):
6973
pubkey = dh
70-
dh = dh.public_numbers().encode_point()
74+
dh = dh.public_bytes(
75+
Encoding.X962,
76+
PublicFormat.UncompressedPoint)
7177
else:
72-
numbers = ec.EllipticCurvePublicNumbers.from_encoded_point(ec.SECP256R1(), dh)
73-
pubkey = numbers.public_key(default_backend())
74-
75-
encoded = private_key.public_key().public_numbers().encode_point()
78+
pubkey = ec.EllipticCurvePublicKey.from_encoded_point(
79+
ec.SECP256R1(),
80+
dh
81+
)
82+
83+
encoded = private_key.public_key().public_bytes(
84+
Encoding.X962,
85+
PublicFormat.UncompressedPoint)
7686
if mode == "encrypt":
7787
sender_pub_key = encoded
7888
receiver_pub_key = dh
@@ -243,7 +253,7 @@ def unpad(data, last):
243253
if version == "aes128gcm":
244254
try:
245255
content_header = parse_content_header(content)
246-
except:
256+
except Exception:
247257
raise ECEException("Could not parse the content header")
248258
salt = content_header['salt']
249259
rs = content_header['rs']
@@ -386,7 +396,9 @@ def compose_aes128gcm(salt, content, rs, keyid):
386396
counter += 1
387397
if version == "aes128gcm":
388398
if keyid is None and private_key is not None:
389-
kid = private_key.public_key().public_numbers().encode_point()
399+
kid = private_key.public_key().public_bytes(
400+
Encoding.X962,
401+
PublicFormat.UncompressedPoint)
390402
else:
391403
kid = (keyid or '').encode('utf-8')
392404
return compose_aes128gcm(salt, result, rs, keyid=kid)

python/http_ece/tests/test_ece.py

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
import unittest
66
from cryptography.hazmat.backends import default_backend
77
from cryptography.hazmat.primitives.asymmetric import ec
8+
from cryptography.hazmat.primitives.serialization import (
9+
Encoding, PublicFormat
10+
)
811

912
from nose.tools import eq_, assert_raises
1013

@@ -43,6 +46,7 @@ def b64d(arg):
4346
return None
4447
return base64.urlsafe_b64decode(str(arg) + '===='[:len(arg) % 4:])
4548

49+
4650
def make_key():
4751
return ec.generate_private_key(ec.SECP256R1(), default_backend())
4852

@@ -131,7 +135,8 @@ class TestEceChecking(unittest.TestCase):
131135
def setUp(self):
132136
self.m_key = os.urandom(16)
133137
self.m_input = os.urandom(5)
134-
# This header is specific to the padding tests, but can be used elsewhere
138+
# This header is specific to the padding tests, but can be used
139+
# elsewhere
135140
self.m_header = b'\xaa\xd2\x05}3S\xb7\xff7\xbd\xe4*\xe1\xd5\x0f\xda'
136141
self.m_header += struct.pack('!L', 32) + b'\0'
137142

@@ -189,47 +194,54 @@ def test_encrypt_long_keyid(self):
189194
self.m_input,
190195
version='aes128gcm',
191196
key=self.m_key,
192-
keyid=b64e(os.urandom(192)), # 256 bytes
197+
keyid=b64e(os.urandom(192)), # 256 bytes
193198
)
194199
eq_(ex.exception.message, "keyid is too long")
195200

196201
def test_overlong_padding(self):
197202
with assert_raises(ECEException) as ex:
198203
ece.decrypt(
199-
self.m_header + b'\xbb\xc7\xb9ev\x0b\xf0f+\x93\xf4\xe5\xd6\x94\xb7e\xf0\xcd\x15\x9b(\x01\xa5',
204+
self.m_header + b'\xbb\xc7\xb9ev\x0b\xf0f+\x93\xf4'
205+
b'\xe5\xd6\x94\xb7e\xf0\xcd\x15\x9b(\x01\xa5',
200206
version='aes128gcm',
201207
key=b'd\xc7\x0ed\xa7%U\x14Q\xf2\x08\xdf\xba\xa0\xb9r',
202-
keyid=b64e(os.urandom(192)), # 256 bytes
208+
keyid=b64e(os.urandom(192)), # 256 bytes
203209
)
204210
eq_(ex.exception.message, "all zero record plaintext")
205211

206212
def test_bad_early_delimiter(self):
207213
with assert_raises(ECEException) as ex:
208214
ece.decrypt(
209-
self.m_header + b'\xb9\xc7\xb9ev\x0b\xf0\x9eB\xb1\x08C8u\xa3\x06\xc9x\x06\n\xfc|}\xe9R\x85\x91\x8bX\x02`\xf3' + b'E8z(\xe5%f/H\xc1\xc32\x04\xb1\x95\xb5N\x9ep\xd4\x0e<\xf3\xef\x0cg\x1b\xe0\x14I~\xdc',
215+
self.m_header + b'\xb9\xc7\xb9ev\x0b\xf0\x9eB\xb1\x08C8u'
216+
b'\xa3\x06\xc9x\x06\n\xfc|}\xe9R\x85\x91'
217+
b'\x8bX\x02`\xf3' +
218+
b'E8z(\xe5%f/H\xc1\xc32\x04\xb1\x95\xb5N\x9ep\xd4\x0e<\xf3'
219+
b'\xef\x0cg\x1b\xe0\x14I~\xdc',
210220
version='aes128gcm',
211221
key=b'd\xc7\x0ed\xa7%U\x14Q\xf2\x08\xdf\xba\xa0\xb9r',
212-
keyid=b64e(os.urandom(192)), # 256 bytes
222+
keyid=b64e(os.urandom(192)), # 256 bytes
213223
)
214224
eq_(ex.exception.message, "record delimiter != 1")
215225

216226
def test_bad_final_delimiter(self):
217227
with assert_raises(ECEException) as ex:
218228
ece.decrypt(
219-
self.m_header + b'\xba\xc7\xb9ev\x0b\xf0\x9eB\xb1\x08Ji\xe4P\x1b\x8dI\xdb\xc6y#MG\xc2W\x16',
229+
self.m_header + b'\xba\xc7\xb9ev\x0b\xf0\x9eB\xb1\x08Ji'
230+
b'\xe4P\x1b\x8dI\xdb\xc6y#MG\xc2W\x16',
220231
version='aes128gcm',
221232
key=b'd\xc7\x0ed\xa7%U\x14Q\xf2\x08\xdf\xba\xa0\xb9r',
222-
keyid=b64e(os.urandom(192)), # 256 bytes
233+
keyid=b64e(os.urandom(192)), # 256 bytes
223234
)
224235
eq_(ex.exception.message, "last record delimiter != 2")
225236

226237
def test_damage(self):
227238
with assert_raises(ECEException) as ex:
228239
ece.decrypt(
229-
self.m_header + b'\xbb\xc6\xb1\x1dF:~\x0f\x07+\xbe\xaaD\xe0\xd6.K\xe5\xf9]%\xe3\x86q\xe0}',
240+
self.m_header + b'\xbb\xc6\xb1\x1dF:~\x0f\x07+\xbe\xaaD'
241+
b'\xe0\xd6.K\xe5\xf9]%\xe3\x86q\xe0}',
230242
version='aes128gcm',
231243
key=b'd\xc7\x0ed\xa7%U\x14Q\xf2\x08\xdf\xba\xa0\xb9r',
232-
keyid=b64e(os.urandom(192)), # 256 bytes
244+
keyid=b64e(os.urandom(192)), # 256 bytes
233245
)
234246
eq_(ex.exception.message, "Decryption error: InvalidTag()")
235247

@@ -246,14 +258,14 @@ def tearDown(self):
246258

247259
def _rsoverhead(self, version):
248260
if version == 'aesgcm128':
249-
return 1;
261+
return 1
250262
if version == 'aesgcm':
251-
return 2;
252-
return 18;
263+
return 2
264+
return 18
253265

254266
def _generate_input(self, minLen=0):
255267
length = struct.unpack('!B', os.urandom(1))[0] + minLen
256-
return os.urandom(length);
268+
return os.urandom(length)
257269

258270
def encrypt_decrypt(self, input, encrypt_params, decrypt_params=None,
259271
version=None):
@@ -263,7 +275,7 @@ def encrypt_decrypt(self, input, encrypt_params, decrypt_params=None,
263275
:type length: bytearray
264276
:param encrypt_params: Dictionary of encryption parameters
265277
:type encrypt_params: dict
266-
:param decrypt_params: Optional dictionary of decryption paramseters
278+
:param decrypt_params: Optional dictionary of decryption parameters
267279
:type decrypt_params: dict
268280
:param version: Content-Type of the body, formulating encryption
269281
:type enumerate("aes128gcm", "aesgcm", "aesgcm128"):
@@ -299,7 +311,8 @@ def encrypt_decrypt(self, input, encrypt_params, decrypt_params=None,
299311
dh=decrypt_params.get("dh"),
300312
private_key=decrypt_params.get("private_key"),
301313
auth_secret=decrypt_params.get("auth_secret"),
302-
rs=decrypt_params.get("rs", decrypt_rs_default),
314+
rs=decrypt_params.get("rs",
315+
decrypt_rs_default),
303316
version=version)
304317
logbuf("Decrypted", decrypted)
305318
eq_(input, decrypted)
@@ -346,12 +359,17 @@ def detect_truncation(self, version):
346359

347360
def use_dh(self, version):
348361
def pubbytes(k):
349-
return k.public_key().public_numbers().encode_point()
362+
return k.public_key().public_bytes(
363+
Encoding.X962,
364+
PublicFormat.UncompressedPoint
365+
)
350366

351367
def privbytes(k):
352368
d = k.private_numbers().private_value
353369
b = b''
354-
for i in range(0, k.private_numbers().public_numbers.curve.key_size, 32):
370+
for i in range(0,
371+
k.private_numbers().public_numbers.curve.key_size,
372+
32):
355373
b = struct.pack("!L", (d >> i) & 0xffffffff) + b
356374
return b
357375

@@ -424,13 +442,11 @@ def _run(self, mode):
424442
if mode == 'encrypt':
425443
func = ece.encrypt
426444
local = 'sender'
427-
remote = 'receiver'
428445
inp = 'input'
429446
outp = 'encrypted'
430447
else:
431448
func = ece.decrypt
432449
local = 'receiver'
433-
remote = 'sender'
434450
inp = 'encrypted'
435451
outp = 'input'
436452

@@ -445,7 +461,8 @@ def _run(self, mode):
445461
if 'keys' in data:
446462
key = None
447463
decode_pub = ec.EllipticCurvePublicNumbers.from_encoded_point
448-
pubnum = decode_pub(ec.SECP256R1(), b64d(data['keys'][local]['public']))
464+
pubnum = decode_pub(ec.SECP256R1(),
465+
b64d(data['keys'][local]['public']))
449466
d = 0
450467
dbin = b64d(data['keys'][local]['private'])
451468
for i in range(0, len(dbin), 4):

0 commit comments

Comments
 (0)