Skip to content

Commit f6e4284

Browse files
committed
bug: fix crypto-key separator
Coverage to 100%
1 parent bc0caeb commit f6e4284

File tree

2 files changed

+58
-28
lines changed

2 files changed

+58
-28
lines changed

python/vapid/__init__.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,22 @@ class Vapid(object):
2121
_private_key = None
2222
_public_key = None
2323

24-
def __init__(self, private_key_file=None):
24+
def __init__(self, private_key_file=None, private_key=None):
2525
"""Initialize VAPID using an optional file containing a private key
2626
in PEM format.
2727
2828
:param private_key_file: The name of the file containing the
2929
private key
3030
"""
3131
if private_key_file:
32+
private_key = open(private_key_file).read()
33+
if private_key:
3234
try:
33-
self.private_key = ecdsa.SigningKey.from_pem(
34-
open(private_key_file).read())
35+
self._private_key = ecdsa.SigningKey.from_pem(private_key)
3536
except Exception, exc:
3637
logging.error("Could not open private key file: %s", repr(exc))
3738
raise VapidException(exc)
38-
self.pubilcKey = self.private_key.get_verifying_key()
39+
self._pubilcKey = self._private_key.get_verifying_key()
3940

4041
@property
4142
def private_key(self):
@@ -72,15 +73,12 @@ def save_public_key(self, key_file):
7273
7374
:param key_file: The name of the file to save the public key
7475
"""
75-
file = open(key_file, "w")
76-
file.write(self.public_key.to_pem())
77-
file.close()
76+
with open(key_file, "w") as file:
77+
file.write(self.public_key.to_pem())
78+
file.close()
7879

7980
def validate(self, token):
80-
try:
81-
return jws.verify(token, self.public_key, algorithms=["ES256"]);
82-
except Exception as e:
83-
raise VapidException(e)
81+
return base64.urlsafe_b64encode(self.private_key.sign(token))
8482

8583
def sign(self, claims, crypto_key=None):
8684
"""Sign a set of claims.
@@ -105,11 +103,9 @@ def sign(self, claims, crypto_key=None):
105103
pkey = 'p256ecdsa='
106104
pkey += base64.urlsafe_b64encode(self.public_key.to_string())
107105
if crypto_key:
108-
crypto_key = crypto_key + ';' + pkey
106+
crypto_key = crypto_key + ',' + pkey
109107
else:
110108
crypto_key = pkey
111109

112110
return {"Authorization": "Bearer " + sig.strip('='),
113111
"Crypto-Key": crypto_key}
114-
115-

python/vapid/tests/test_vapid.py

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
# This Source Code Form is subject to the terms of the Mozilla Public
2-
# License, v. 2.0. If a copy of the MPL was not distributed with this
3-
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4-
51
import base64
62
import os
73
import json
84
import unittest
95
from nose.tools import eq_, ok_
6+
from mock import patch
107

118
from jose import jws
129
from vapid import Vapid, VapidException
@@ -26,8 +23,12 @@
2623

2724

2825
def setUp(self):
29-
open('/tmp/private', 'w').write(T_PRIVATE)
30-
open('/tmp/public', 'w').write(T_PUBLIC)
26+
ff = open('/tmp/private', 'w')
27+
ff.write(T_PRIVATE)
28+
ff.close()
29+
ff = open('/tmp/public', 'w')
30+
ff.write(T_PUBLIC)
31+
ff.close()
3132

3233

3334
def tearDown(self):
@@ -37,9 +38,18 @@ def tearDown(self):
3738

3839
class VapidTestCase(unittest.TestCase):
3940
def test_init(self):
40-
v = Vapid("/tmp/private")
41-
eq_(v.private_key.to_pem(), T_PRIVATE)
42-
eq_(v.public_key.to_pem(), T_PUBLIC)
41+
v1 = Vapid(private_key_file="/tmp/private")
42+
eq_(v1.private_key.to_pem(), T_PRIVATE)
43+
eq_(v1.public_key.to_pem(), T_PUBLIC)
44+
v2 = Vapid(private_key=T_PRIVATE)
45+
eq_(v2.private_key.to_pem(), T_PRIVATE)
46+
eq_(v2.public_key.to_pem(), T_PUBLIC)
47+
48+
@patch("ecdsa.SigningKey.from_pem", side_effect=Exception)
49+
def test_init_bad_priv(self, mm):
50+
self.assertRaises(Exception,
51+
Vapid,
52+
private_key_file="/tmp/private")
4353

4454
def test_private(self):
4555
v = Vapid()
@@ -63,22 +73,46 @@ def test_gen_key(self):
6373
ok_(v.public_key)
6474
ok_(v.private_key)
6575

76+
def test_save_key(self):
77+
v = Vapid()
78+
v.save_key("/tmp/p2")
79+
os.unlink("/tmp/p2")
80+
81+
def test_save_public_key(self):
82+
v = Vapid()
83+
v.generate_keys()
84+
v.save_public_key("/tmp/p2")
85+
os.unlink("/tmp/p2")
86+
6687
def test_validate(self):
6788
v = Vapid("/tmp/private")
68-
claims = {"aud": "example.com", "sub": "admin@example.com"}
69-
result = jws.sign(claims, v.private_key, algorithm="ES256")
70-
msg = v.validate(result)
71-
eq_(claims, json.loads(msg))
89+
msg = "foobar"
90+
vtoken = v.validate(msg)
91+
ok_(v.public_key.verify(base64.urlsafe_b64decode(vtoken), msg))
7292

7393
def test_sign(self):
7494
v = Vapid("/tmp/private")
7595
claims = {"aud": "example.com", "sub": "admin@example.com"}
76-
result = v.sign(claims)
96+
result = v.sign(claims, "id=previous")
7797
eq_(result['Crypto-Key'],
98+
'id=previous,'
7899
'p256ecdsa=EJwJZq_GN8jJbo1GGpyU70hmP2hbWAUpQFKDBy'
79100
'KB81yldJ9GTklBM5xqEwuPM7VuQcyiLDhvovthPIXx-gsQRQ==')
80101
items = jws.verify(result['Authorization'][7:],
81102
v.public_key,
82103
algorithms=["ES256"])
83104
eq_(json.loads(items), claims)
105+
result = v.sign(claims)
106+
eq_(result['Crypto-Key'],
107+
'p256ecdsa=EJwJZq_GN8jJbo1GGpyU70hmP2hbWAUpQFKDBy'
108+
'KB81yldJ9GTklBM5xqEwuPM7VuQcyiLDhvovthPIXx-gsQRQ==')
109+
110+
def test_bad_sign(self):
111+
v = Vapid("/tmp/private")
112+
self.assertRaises(VapidException,
113+
v.sign,
114+
{'sub': "a@e.c"})
115+
self.assertRaises(VapidException,
116+
v.sign,
117+
{'aud': "https://e.c"})
84118

0 commit comments

Comments
 (0)