Skip to content

Commit be3e94d

Browse files
author
Roland Hedberg
committed
Merge pull request #34 from rebeckag/fix_tests
Fixes tests and make them run on Travis
2 parents 337b0ca + 49f0a9a commit be3e94d

6 files changed

Lines changed: 171 additions & 191 deletions

File tree

.travis.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
language: python
22

3+
sudo: false
4+
5+
addons:
6+
apt:
7+
packages:
8+
- libgmp-dev
9+
310
env:
411
- TOX_ENV=py27
512
- TOX_ENV=py34
613

714
install:
815
- pip install -U tox
9-
- sudo apt-get -qq install libgmp-dev
10-
16+
1117
script:
1218
- tox -e $TOX_ENV

setup.py

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,11 @@
1515
# limitations under the License.
1616
#
1717

18-
from setuptools import setup
1918
import glob
20-
import sys
21-
from setuptools.command.test import test as TestCommand
22-
23-
__author__ = 'rohe0002'
24-
2519

26-
class PyTest(TestCommand):
27-
def finalize_options(self):
28-
TestCommand.finalize_options(self)
29-
self.test_args = []
30-
self.test_suite = True
31-
32-
def run_tests(self):
33-
#import here, cause outside the eggs aren't loaded
34-
import pytest
35-
36-
errno = pytest.main(self.test_args)
37-
sys.exit(errno)
20+
from setuptools import setup
3821

22+
__author__ = 'rohe0002'
3923

4024
setup(
4125
name="pyjwkest",
@@ -55,6 +39,5 @@ def run_tests(self):
5539
install_requires=["pycrypto >= 2.6.1", "requests", "six", "future"],
5640
tests_require=['pytest'],
5741
zip_safe=False,
58-
cmdclass={'test': PyTest},
5942
scripts=glob.glob('script/*.py'),
6043
)

src/jwkest/ecc.py

Lines changed: 10 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
#!/usr/bin/env python
22

3+
# pylint: disable=invalid-name
4+
35
from __future__ import print_function
46
from __future__ import absolute_import
57
from __future__ import division
6-
import six
78

8-
try:
9-
from builtins import object
10-
except ImportError:
11-
pass
12-
#from past.utils import old_div
139
from Crypto.Util.number import long_to_bytes, bytes_to_long
1410
from jwkest.elliptic import inv, mulp, sign_bit, y_from_x, muladdp
1511
from jwkest.curves import get_curve
@@ -22,7 +18,6 @@ class NISTEllipticCurve(object):
2218
def __init__(self, bits):
2319
# (bits, prime, order, p, q, point)
2420
(self.bits, self.p, self.N, self.a, self.b, self.G) = get_curve(bits)
25-
# self.bytes = int(ceil(div(self.bits, 8.0)))
2621
self.bytes = int(ceil(self.bits / 8.0))
2722

2823
@staticmethod
@@ -35,7 +30,7 @@ def by_name(name):
3530
return NISTEllipticCurve(521)
3631
else:
3732
raise Exception("Unknown curve {}".format(name))
38-
33+
3934
# Get the name of this curve
4035
# XXX This only works because we only support prime curves right now
4136
def name(self):
@@ -44,7 +39,7 @@ def name(self):
4439
# Integer-to-byte-string conversion
4540
def int2bytes(self, x):
4641
return long_to_bytes(x, self.bytes)
47-
42+
4843
@staticmethod
4944
def bytes2int(x):
5045
return bytes_to_long(x)
@@ -64,12 +59,12 @@ def key_pair(self):
6459
return priv, pub
6560

6661
def public_key_for(self, priv):
67-
return mulp(self.a, self.b, self.p, self.G, priv )
62+
return mulp(self.a, self.b, self.p, self.G, priv)
6863

69-
# Compute the DH shared secret (X coordinate) from a public key and private
64+
# Compute the DH shared secret (X coordinate) from a public key and private
7065
# key
7166
def dh_z(self, priv, pub):
72-
return self.int2bytes( mulp(self.a, self.b, self.p, pub, priv)[0] )
67+
return self.int2bytes(mulp(self.a, self.b, self.p, pub, priv)[0])
7368

7469
def _sign_loop(self, r, s, h, k, priv):
7570
while r == 0 or s == 0:
@@ -88,10 +83,7 @@ def sign(self, h, priv, k=None):
8883
while h > self.N:
8984
h >>= 1
9085

91-
if six.PY2:
92-
r = s = 0L
93-
else:
94-
r = s = 0
86+
r = s = 0
9587

9688
r, s = self._sign_loop(r, s, h, k, priv)
9789

@@ -101,7 +93,7 @@ def verify(self, h, sig, pub):
10193
while h > self.N:
10294
h >>= 1
10395
r = self.bytes2int(sig[:self.bytes])
104-
s = self.bytes2int(sig[self.bytes:])
96+
s = self.bytes2int(sig[self.bytes:])
10597
if 0 < r < self.N and 0 < s < self.N:
10698
w = inv(s, self.N)
10799
u1 = (h * w) % self.N
@@ -110,141 +102,7 @@ def verify(self, h, sig, pub):
110102
return r % self.N == x % self.N
111103
return False
112104

105+
113106
P256 = NISTEllipticCurve(256)
114107
P384 = NISTEllipticCurve(384)
115108
P521 = NISTEllipticCurve(521)
116-
117-
if __name__ == "__main__":
118-
# Try ECDH, see if we get the same answer
119-
(privA, pubA) = P256.key_pair()
120-
(privB, pubB) = P256.key_pair()
121-
122-
Zab = P256.dh_z(privA, pubB)
123-
Zba = P256.dh_z(privB, pubA)
124-
125-
if Zab == Zba:
126-
print("Passed DH test")
127-
else:
128-
print("Failed DH test")
129-
130-
# Try ECDSA with one of the NIST test vectors
131-
import hashlib
132-
_msg = ("5ff1fa17c2a67ce599a34688f6fb2d4a8af17532d15fa1868a598a8e6a0daf9b11"
133-
"edcc483d11ae003ed645c0aaccfb1e51cf448b737376d531a6dcf0429005f5e7be"
134-
"626b218011c6218ff32d00f30480b024ec9a3370d1d30a9c70c9f1ce6c61c9abe5"
135-
"08d6bc4d3f2a167756613af1778f3a94e7771d5989fe856fa4df8f8ae5")
136-
msg = _msg.decode("hex")
137-
d = 0x002a10b1b5b9fa0b78d38ed29cd9cec18520e0fe93023e3550bb7163ab4905c6
138-
k = 0x00c2815763d7fcb2480b39d154abc03f616f0404e11272d624e825432687092a
139-
Qx = 0xe9cd2e8f15bd90cb0707e05ed3b601aace7ef57142a64661ea1dd7199ebba9ac
140-
Qy = 0xc96b0115bed1c134b68f89584b040a194bfad94a404fdb37adad107d5a0b4c5e
141-
Q = (Qx, Qy)
142-
R = 0x15bf46937c7a1e2fa7adc65c89fe03ae602dd7dfa6722cdafa92d624b32b156e
143-
S = 0x59c591792ee94f0b202e7a590e70d01dd8a9774884e2b5ba9945437cfed01686
144-
145-
h = int(hashlib.new("SHA1", msg).hexdigest(), 16)
146-
sig = P256.int2bytes(R) + P256.int2bytes(S)
147-
ver = P256.verify(h, sig, Q)
148-
if ver:
149-
print("Passed NIST ECDSA P-256 verification test")
150-
else:
151-
print("Failed NIST ECDSA P-256 verification test")
152-
153-
# NB: This will differ because of k; fix k to test generation
154-
sig = P256.sign(h, d)
155-
ver2 = P256.verify(h, sig, Q)
156-
if ver2:
157-
print("Passed ECDSA P-256 signature test")
158-
else:
159-
print("Failed ECDSA P-256 signature test")
160-
161-
162-
# Try ECDSA with the Suite B test vectors
163-
msg = ("54686973206973206f6e6c7920612074657374206d6573736167652e2049742069"
164-
"73203438206279746573206c6f6e67").decode("hex")
165-
Qx = 0x1fbac8eebd0cbf35640b39efe0808dd774debff20a2a329e91713baf7d7f3c3e81546d883730bee7e48678f857b02ca0
166-
Qy = 0xeb213103bd68ce343365a8a4c3d4555fa385f5330203bdd76ffad1f3affb95751c132007e1b240353cb0a4cf1693bdf9
167-
R = 0xa0c27ec893092dea1e1bd2ccfed3cf945c8134ed0c9f81311a0f4a05942db8dbed8dd59f267471d5462aa14fe72de856
168-
S = 0x20ab3f45b74f10b6e11f96a2c8eb694d206b9dda86d3c7e331c26b22c987b7537726577667adadf168ebbe803794a402
169-
170-
h = int(hashlib.new("SHA384", msg).hexdigest(), 16)
171-
Q = (Qx, Qy)
172-
sig = P384.int2bytes(R) + P384.int2bytes(S)
173-
ver = P384.verify(h, sig, Q)
174-
if ver:
175-
print("Passed Suite B ECDSA P-384 verification test")
176-
else:
177-
print("Failed Suite B ECDSA P-384 verification test")
178-
179-
msg = ("54686973206973206f6e6c7920612074657374206d6573736167652e2049742069"
180-
"73203438206279746573206c6f6e67").decode("hex")
181-
Qx = 0x8101ece47464a6ead70cf69a6e2bd3d88691a3262d22cba4f7635eaff26680a8
182-
Qy = 0xd8a12ba61d599235f67d9cb4d58f1783d3ca43e78f0a5abaa624079936c0c3a9
183-
R = 0x7214bc9647160bbd39ff2f80533f5dc6ddd70ddf86bb815661e805d5d4e6f27c
184-
S = 0x7d1ff961980f961bdaa3233b6209f4013317d3e3f9e1493592dbeaa1af2bc367
185-
186-
h = int(hashlib.new("SHA256", msg).hexdigest(), 16)
187-
Q = (Qx, Qy)
188-
sig = P256.int2bytes(R) + P256.int2bytes(S)
189-
ver = P256.verify(h, sig, Q)
190-
if ver:
191-
print("Passed Suite B ECDSA P-256 verification test")
192-
else:
193-
print("Failed Suite B ECDSA P-256 verification test")
194-
195-
# Try ECDSA with one of the NIST P-521 test vectors (should pass)
196-
_sg = ("f69417bead3b1e208c4c99236bf84474a00de7f0b9dd23f991b6b60ef0fb3c6207"
197-
"3a5a7abb1ef69dbbd8cf61e64200ca086dfd645b641e8d02397782da92d3542fbd"
198-
"df6349ac0b48b1b1d69fe462d1bb492f34dd40d137163843ac11bd099df719212c"
199-
"160cbebcb2ab6f3525e64846c887e1b52b52eced9447a3d31938593a87")
200-
msg = _sg.decode("hex")
201-
Qx = 0x153eb2be05438e5c1effb41b413efc2843b927cbf19f0bc9cc14b693eee26394a0d8880dc946a06656bcd09871544a5f15c7a1fa68e00cdc728c7cfb9c448034867
202-
Qy = 0x143ae8eecbce8fcf6b16e6159b2970a9ceb32c17c1d878c09317311b7519ed5ece3374e7929f338ddd0ec0522d81f2fa4fa47033ef0c0872dc049bb89233eef9bc1
203-
R = 0x0dd633947446d0d51a96a0173c01125858abb2bece670af922a92dedcec067136c1fa92e5fa73d7116ac9c1a42b9cb642e4ac19310b049e48c53011ffc6e7461c36
204-
S = 0x0efbdc6a414bb8d663bb5cdb7c586bccfe7589049076f98cee82cdb5d203fddb2e0ffb77954959dfa5ed0de850e42a86f5a63c5a6592e9b9b8bd1b40557b9cd0cc0
205-
206-
h = int(hashlib.new("SHA512", msg).hexdigest(), 16)
207-
Q = (Qx, Qy)
208-
sig = P521.int2bytes(R) + P521.int2bytes(S)
209-
ver = P521.verify(h, sig, Q)
210-
if ver:
211-
print("Passed NIST ECDSA P-521 verification test")
212-
else:
213-
print("Failed NIST ECDSA P-521 verification test")
214-
215-
216-
# Try ECDSA with one of the NIST P-521 test vectors (should fail)
217-
_sg = ("a0732a605c785a2cc9a3ff84cbaf29175040f7a0cc35f4ea8eeff267c1f92f06f4"
218-
"6d3b35437195185d322cbd775fd24741e86ee9236ba5b374a2ac29803554d715fa"
219-
"4656ac31778f103f88d68434dd2013d4c4e9848a11198b390c3d600d712893513e"
220-
"179cd3d31fb06c6e2a1016fb96ffd970b1489e36a556ab3b537eb29dff")
221-
msg = _sg.decode("hex")
222-
Qx = 0x12a593f568ca2571e543e00066ecd3a3272a57e1c94fe311e5df96afc1b792e5862720fc730e62052bbf3e118d3a078f0144fc00c9d8baaaa8298ff63981d09d911
223-
Qy = 0x17cea5ae75a74100ee03cdf2468393eef55ddabfe8fd5718e88903eb9fd241e8cbf9c68ae16f4a1db26c6352afcb1894a9812da6d32cb862021c86cd8aa483afc26
224-
R = 0x1aac7692baf3aa94a97907307010895efc1337cdd686f9ef2fd8404796a74701e55b03ceef41f3e6f50a0eeea11869c4789a3e8ab5b77324961d081e1a3377ccc91
225-
S = 0x009c1e7d93d056b5a97759458d58c49134a45071854b8a6b8272f9fe7e78e1f3d8097e8a6e731f7ab4851eb26d5aa4fdadba6296dc7af835fe3d1b6dba4b031d5f3
226-
227-
h = int(hashlib.new("SHA512", msg).hexdigest(), 16)
228-
Q = (Qx, Qy)
229-
sig = P521.int2bytes(R) + P521.int2bytes(S)
230-
ver = P521.verify(h, sig, Q)
231-
if not ver:
232-
print("Passed NIST ECDSA P-521 negative verification test")
233-
else:
234-
print("Failed NIST ECDSA P-521 negative verification test")
235-
236-
# Try ECDSA on our own signature with P-521
237-
_sg = ("9ce982c91af08a21d405f96abd6204588bb0ef1c8b78305b06f36a12d1914cae9d"
238-
"ce6a1f1a0b4c42b067667c457c3e90e56f34cff0116bbd350d27882dd6e47997c9"
239-
"44dcead9cb945f7c691078c1b533960a55f93d241970a1fdf4441107d8bc8af5aa"
240-
"8e088ea3aa82c7f3286e815dbb85d5cfae0aeeeb093468cb55201eeffb")
241-
msg = _sg.decode("hex")
242-
243-
(priv, pub) = P521.key_pair()
244-
h = int(hashlib.new("SHA512", msg).hexdigest(), 16)
245-
sig = P521.sign(h, priv)
246-
ver = P521.verify(h, sig, pub)
247-
if ver:
248-
print("Passed self-interop with P-521")
249-
else:
250-
print("Failed self-interop with P-521")

tests/test_2_jwk.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import print_function
22
import base64
3+
from collections import Counter
34
import json
45
from Crypto.PublicKey import RSA
56
from Crypto.PublicKey.RSA import _RSAobj
@@ -26,6 +27,7 @@
2627
def full_path(local_file):
2728
return os.path.join(BASEDIR, local_file)
2829

30+
2931
CERT = full_path("cert.pem")
3032
KEY = full_path("server.key")
3133

@@ -39,7 +41,7 @@ def full_path(local_file):
3941

4042

4143
def _eq(l1, l2):
42-
return set(l1) == set(l2)
44+
return Counter(l1) == Counter(l2)
4345

4446

4547
def test_urlsafe_base64decode():
@@ -163,12 +165,13 @@ def test_load_jwk():
163165

164166

165167
def test_import_rsa_key():
166-
_ckey = RSA.importKey(open(KEY, 'r').read())
168+
_ckey = RSA.importKey(open(full_path(KEY), 'r').read())
167169
assert isinstance(_ckey, _RSAobj)
168170
djwk = jwk_wrap(_ckey).to_dict()
169171
print(djwk)
170-
assert _eq(list(djwk.keys()), ["kty", "e", "n", "d"])
171-
assert djwk["n"] == b'5zbNbHIYIkGGJ3RGdRKkYmF4gOorv5eDuUKTVtuu3VvxrpOWvwnFV-NY0LgqkQSMMyVzodJE3SUuwQTUHPXXY5784vnkFqzPRx6bHgPxKz7XfwQjEBTafQTMmOeYI8wFIOIHY5i0RWR-gxDbh_D5TXuUqScOOqR47vSpIbUH-nc'
172+
assert _eq(djwk.keys(), ["kty", "e", "n", "p", "q", "d"])
173+
assert djwk[
174+
"n"] == b'5zbNbHIYIkGGJ3RGdRKkYmF4gOorv5eDuUKTVtuu3VvxrpOWvwnFV-NY0LgqkQSMMyVzodJE3SUuwQTUHPXXY5784vnkFqzPRx6bHgPxKz7XfwQjEBTafQTMmOeYI8wFIOIHY5i0RWR-gxDbh_D5TXuUqScOOqR47vSpIbUH-nc'
172175
assert djwk['e'] == b'AQAB'
173176

174177

@@ -181,6 +184,7 @@ def test_serialize_rsa_pub_key():
181184

182185
assert rsa_eq(restored_key, rsakey)
183186

187+
184188
def test_serialize_rsa_priv_key():
185189
rsakey = RSAKey(key=import_rsa_key_from_file(full_path("rsa.key")))
186190
assert rsakey.d
@@ -276,7 +280,7 @@ def test_cmp_neq_ec():
276280
"y": u'GOd2jL_6wa0cfnyA0SmEhok9fkYEnAHFKLLM79BZ8_E',
277281
"crv": "P-256"
278282
}
279-
]}
283+
]}
280284

281285

282286
def test_keys():
@@ -291,10 +295,11 @@ def test_keys():
291295
assert len(keyl['oct']) == 1
292296
assert len(keyl['ec']) == 1
293297

298+
294299
def test_private_key_from_jwk():
295300
keys = []
296301

297-
kspec = json.loads(open("jwk_private_key.json").read())
302+
kspec = json.loads(open(full_path("jwk_private_key.json")).read())
298303
keys.append(keyrep(kspec))
299304

300305
key = keys[0]
@@ -316,5 +321,6 @@ def test_private_key_from_jwk():
316321
'kty', 'qi'])
317322
assert _eq(list(_d.keys()), kspec.keys())
318323

324+
319325
if __name__ == "__main__":
320-
test_private_key_from_jwk()
326+
test_private_key_from_jwk()

0 commit comments

Comments
 (0)