Skip to content

Commit b5bc420

Browse files
committed
Parametrize tests of backends whenever possible.
Some tests had duplicated code within them to test for backends, and for other tests there were different testing harnesses that tested parts of each backend. This commit unifies the tests to be as backend-agnostic as possible, and execute them for each backend using pytest's parametrization.
1 parent 71e6cf0 commit b5bc420

File tree

3 files changed

+139
-207
lines changed

3 files changed

+139
-207
lines changed

tests/algorithms/test_EC.py

Lines changed: 73 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,66 @@
1717

1818
class TestECAlgorithm:
1919

20-
def test_EC_key(self):
21-
key = ecdsa.SigningKey.from_pem(private_key)
22-
assert not ECDSAECKey(key, ALGORITHMS.ES256).is_public()
23-
assert not CryptographyECKey(key, ALGORITHMS.ES256).is_public()
24-
25-
assert not ECDSAECKey(private_key, ALGORITHMS.ES256).is_public()
26-
assert not CryptographyECKey(private_key, ALGORITHMS.ES256).is_public()
20+
@pytest.mark.parametrize("Backend", [ECDSAECKey, CryptographyECKey])
21+
def test_key_from_pem(self, Backend):
22+
assert not Backend(private_key, ALGORITHMS.ES256).is_public()
2723

28-
def test_string_secret(self):
24+
@pytest.mark.parametrize("Backend", [ECDSAECKey, CryptographyECKey])
25+
def test_key_from_ecdsa(self, Backend):
26+
key = ecdsa.SigningKey.from_pem(private_key)
27+
assert not Backend(key, ALGORITHMS.ES256).is_public()
28+
29+
@pytest.mark.parametrize("Backend", [ECDSAECKey, CryptographyECKey])
30+
def test_to_pem(self, Backend):
31+
key = Backend(private_key, ALGORITHMS.ES256)
32+
assert not key.is_public()
33+
assert key.to_pem().strip() == private_key.strip().encode('utf-8')
34+
35+
public_pem = key.public_key().to_pem()
36+
assert Backend(public_pem, ALGORITHMS.ES256).is_public()
37+
38+
@pytest.mark.parametrize(
39+
"Backend,ExceptionType",
40+
[
41+
(ECDSAECKey, ecdsa.BadDigestError),
42+
(CryptographyECKey, TypeError)
43+
]
44+
)
45+
def test_key_too_short(self, Backend, ExceptionType):
46+
priv_key = ecdsa.SigningKey.generate(curve=ecdsa.NIST256p).to_pem()
47+
key = Backend(priv_key, ALGORITHMS.ES512)
48+
with pytest.raises(ExceptionType):
49+
key.sign(b'foo')
50+
51+
@pytest.mark.parametrize("Backend", [ECDSAECKey, CryptographyECKey])
52+
def test_get_public_key(self, Backend):
53+
key = Backend(private_key, ALGORITHMS.ES256)
54+
pubkey = key.public_key()
55+
pubkey2 = pubkey.public_key()
56+
assert pubkey == pubkey2
57+
58+
@pytest.mark.parametrize("Backend", [ECDSAECKey, CryptographyECKey])
59+
def test_string_secret(self, Backend):
2960
key = 'secret'
3061
with pytest.raises(JOSEError):
31-
ECDSAECKey(key, ALGORITHMS.ES256)
32-
33-
with pytest.raises(JOSEError):
34-
CryptographyECKey(key, ALGORITHMS.ES256)
62+
Backend(key, ALGORITHMS.ES256)
3563

36-
def test_object(self):
64+
@pytest.mark.parametrize("Backend", [ECDSAECKey, CryptographyECKey])
65+
def test_object(self, Backend):
3766
key = object()
3867
with pytest.raises(JOSEError):
39-
ECDSAECKey(key, ALGORITHMS.ES256)
68+
Backend(key, ALGORITHMS.ES256)
4069

41-
with pytest.raises(JOSEError):
42-
CryptographyECKey(key, ALGORITHMS.ES256)
70+
@pytest.mark.parametrize("Backend", [ECDSAECKey, CryptographyECKey])
71+
def test_invalid_algorithm(self, Backend):
72+
with pytest.raises(JWKError):
73+
Backend(private_key, 'nonexistent')
4374

44-
def test_invalid_algorithm(self):
4575
with pytest.raises(JWKError):
46-
ECDSAECKey({'kty': 'bla'}, ALGORITHMS.ES256)
76+
Backend({'kty': 'bla'}, ALGORITHMS.ES256)
4777

48-
def test_EC_jwk(self):
78+
@pytest.mark.parametrize("Backend", [ECDSAECKey, CryptographyECKey])
79+
def test_EC_jwk(self, Backend):
4980
key = {
5081
"kty": "EC",
5182
@@ -56,26 +87,22 @@ def test_EC_jwk(self):
5687
"d": "AAhRON2r9cqXX1hg-RoI6R1tX5p2rUAYdmpHZoC1XNM56KtscrX6zbKipQrCW9CGZH3T4ubpnoTKLDYJ_fF3_rJt",
5788
}
5889

59-
assert not ECDSAECKey(key, ALGORITHMS.ES512).is_public()
60-
assert not CryptographyECKey(key, ALGORITHMS.ES512).is_public()
90+
assert not Backend(key, ALGORITHMS.ES512).is_public()
6191

6292
del key['d']
6393

6494
# We are now dealing with a public key.
65-
assert ECDSAECKey(key, ALGORITHMS.ES512).is_public()
66-
assert CryptographyECKey(key, ALGORITHMS.ES512).is_public()
95+
assert Backend(key, ALGORITHMS.ES512).is_public()
6796

6897
del key['x']
6998

7099
# This key is missing a required parameter.
71100
with pytest.raises(JWKError):
72-
ECDSAECKey(key, ALGORITHMS.ES512)
101+
Backend(key, ALGORITHMS.ES512)
73102

74-
with pytest.raises(JWKError):
75-
CryptographyECKey(key, ALGORITHMS.ES512)
76-
77-
def test_verify(self):
78-
key = ECDSAECKey(private_key, ALGORITHMS.ES256)
103+
@pytest.mark.parametrize("Backend", [ECDSAECKey])
104+
def test_verify(self, Backend):
105+
key = Backend(private_key, ALGORITHMS.ES256)
79106
msg = b'test'
80107
signature = key.sign(msg)
81108
public_key = key.public_key()
@@ -102,11 +129,23 @@ def assert_parameters(self, as_dict, private):
102129
# Private parameters should be absent
103130
assert 'd' not in as_dict
104131

105-
def test_to_dict(self):
106-
key = CryptographyECKey(private_key, ALGORITHMS.ES256)
132+
@pytest.mark.parametrize("Backend", [ECDSAECKey, CryptographyECKey])
133+
def test_to_dict(self, Backend):
134+
key = Backend(private_key, ALGORITHMS.ES256)
107135
self.assert_parameters(key.to_dict(), private=True)
108136
self.assert_parameters(key.public_key().to_dict(), private=False)
109137

110-
key = ECDSAECKey(private_key, ALGORITHMS.ES256)
111-
self.assert_parameters(key.to_dict(), private=True)
112-
self.assert_parameters(key.public_key().to_dict(), private=False)
138+
@pytest.mark.parametrize("BackendSign", [ECDSAECKey, CryptographyECKey])
139+
@pytest.mark.parametrize("BackendVerify", [ECDSAECKey, CryptographyECKey])
140+
def test_signing_parity(self, BackendSign, BackendVerify):
141+
key_sign = BackendSign(private_key, ALGORITHMS.ES256)
142+
key_verify = BackendVerify(private_key, ALGORITHMS.ES256).public_key()
143+
144+
msg = b'test'
145+
sig = key_sign.sign(msg)
146+
147+
# valid signature
148+
assert key_verify.verify(msg, sig)
149+
150+
# invalid signature
151+
assert not key_verify.verify(msg, b'n' * 64)

tests/algorithms/test_RSA.py

Lines changed: 66 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -70,34 +70,15 @@
7070

7171
class TestRSAAlgorithm:
7272

73-
def test_RSA_key(self):
74-
RSAKey(private_key, ALGORITHMS.RS256)
73+
@pytest.mark.parametrize("Backend", [RSAKey, CryptographyRSAKey])
74+
def test_RSA_key(self, Backend):
75+
assert not Backend(private_key, ALGORITHMS.RS256).is_public()
7576

76-
def test_RSA_key_instance(self):
77+
def test_pycrypto_RSA_key_instance(self):
7778
key = RSA.construct((long(26057131595212989515105618545799160306093557851986992545257129318694524535510983041068168825614868056510242030438003863929818932202262132630250203397069801217463517914103389095129323580576852108653940669240896817348477800490303630912852266209307160550655497615975529276169196271699168537716821419779900117025818140018436554173242441334827711966499484119233207097432165756707507563413323850255548329534279691658369466534587631102538061857114141268972476680597988266772849780811214198186940677291891818952682545840788356616771009013059992237747149380197028452160324144544057074406611859615973035412993832273216732343819), long(65537)))
7879
RSAKey(key, ALGORITHMS.RS256)
7980

80-
def test_string_secret(self):
81-
key = 'secret'
82-
with pytest.raises(JOSEError):
83-
RSAKey(key, ALGORITHMS.RS256)
84-
85-
def test_object(self):
86-
key = object()
87-
with pytest.raises(JOSEError):
88-
RSAKey(key, ALGORITHMS.RS256)
89-
90-
def test_bad_cert(self):
91-
key = '-----BEGIN CERTIFICATE-----'
92-
with pytest.raises(JOSEError):
93-
RSAKey(key, ALGORITHMS.RS256)
94-
95-
96-
class TestRSACryptography:
97-
def test_RSA_key(self):
98-
assert not CryptographyRSAKey(private_key, ALGORITHMS.RS256).is_public()
99-
100-
def test_RSA_key_instance(self):
81+
def test_cryptography_RSA_key_instance(self):
10182
from cryptography.hazmat.backends import default_backend
10283
from cryptography.hazmat.primitives.asymmetric import rsa
10384

@@ -112,21 +93,40 @@ def test_RSA_key_instance(self):
11293
pem = pubkey.to_pem()
11394
assert pem.startswith(b'-----BEGIN PUBLIC KEY-----')
11495

115-
def test_invalid_algorithm(self):
96+
@pytest.mark.parametrize("Backend", [RSAKey, CryptographyRSAKey])
97+
def test_string_secret(self, Backend):
98+
key = 'secret'
99+
with pytest.raises(JOSEError):
100+
Backend(key, ALGORITHMS.RS256)
101+
102+
@pytest.mark.parametrize("Backend", [RSAKey, CryptographyRSAKey])
103+
def test_object(self, Backend):
104+
key = object()
105+
with pytest.raises(JOSEError):
106+
Backend(key, ALGORITHMS.RS256)
107+
108+
@pytest.mark.parametrize("Backend", [RSAKey, CryptographyRSAKey])
109+
def test_bad_cert(self, Backend):
110+
key = '-----BEGIN CERTIFICATE-----'
111+
with pytest.raises(JOSEError):
112+
Backend(key, ALGORITHMS.RS256)
113+
114+
@pytest.mark.parametrize("Backend", [RSAKey, CryptographyRSAKey])
115+
def test_invalid_algorithm(self, Backend):
116116
with pytest.raises(JWKError):
117-
CryptographyRSAKey(private_key, ALGORITHMS.ES256)
117+
Backend(private_key, ALGORITHMS.ES256)
118118

119119
with pytest.raises(JWKError):
120-
CryptographyRSAKey({'kty': 'bla'}, ALGORITHMS.RS256)
120+
Backend({'kty': 'bla'}, ALGORITHMS.RS256)
121121

122-
def test_RSA_jwk(self):
122+
@pytest.mark.parametrize("Backend", [RSAKey, CryptographyRSAKey])
123+
def test_RSA_jwk(self, Backend):
123124
key = {
124125
"kty": "RSA",
125126
"n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
126127
"e": "AQAB",
127128
}
128-
assert CryptographyRSAKey(key, ALGORITHMS.RS256).is_public()
129-
assert RSAKey(key, ALGORITHMS.RS256).is_public()
129+
assert Backend(key, ALGORITHMS.RS256).is_public()
130130

131131
key = {
132132
"kty": "RSA",
@@ -141,62 +141,40 @@ def test_RSA_jwk(self):
141141
"dq": "CLDmDGduhylc9o7r84rEUVn7pzQ6PF83Y-iBZx5NT-TpnOZKF1pErAMVeKzFEl41DlHHqqBLSM0W1sOFbwTxYWZDm6sI6og5iTbwQGIC3gnJKbi_7k_vJgGHwHxgPaX2PnvP-zyEkDERuf-ry4c_Z11Cq9AqC2yeL6kdKT1cYF8",
142142
"qi": "3PiqvXQN0zwMeE-sBvZgi289XP9XCQF3VWqPzMKnIgQp7_Tugo6-NZBKCQsMf3HaEGBjTVJs_jcK8-TRXvaKe-7ZMaQj8VfBdYkssbu0NKDDhjJ-GtiseaDVWt7dcH0cfwxgFUHpQh7FoCrjFJ6h6ZEpMF6xmujs4qMpPz8aaI4"
143143
}
144-
assert not CryptographyRSAKey(key, ALGORITHMS.RS256).is_public()
145-
assert not RSAKey(key, ALGORITHMS.RS256).is_public()
144+
assert not Backend(key, ALGORITHMS.RS256).is_public()
146145

147146
del key['p']
148147

149148
# Some but not all extra parameters are present
150149
with pytest.raises(JWKError):
151-
CryptographyRSAKey(key, ALGORITHMS.RS256)
152-
153-
with pytest.raises(JWKError):
154-
RSAKey(key, ALGORITHMS.RS256)
150+
Backend(key, ALGORITHMS.RS256)
155151

156152
del key['q']
157153
del key['dp']
158154
del key['dq']
159155
del key['qi']
160156

161157
# None of the extra parameters are present, but 'key' is still private.
162-
assert not CryptographyRSAKey(key, ALGORITHMS.RS256).is_public()
163-
assert not RSAKey(key, ALGORITHMS.RS256).is_public()
158+
assert not Backend(key, ALGORITHMS.RS256).is_public()
164159

165-
def test_string_secret(self):
160+
@pytest.mark.parametrize("Backend", [RSAKey, CryptographyRSAKey])
161+
def test_string_secret(self, Backend):
166162
key = 'secret'
167163
with pytest.raises(JOSEError):
168-
CryptographyRSAKey(key, ALGORITHMS.RS256)
164+
Backend(key, ALGORITHMS.RS256)
169165

170-
def test_object(self):
171-
key = object()
172-
with pytest.raises(JOSEError):
173-
CryptographyRSAKey(key, ALGORITHMS.RS256)
174-
175-
def test_bad_cert(self):
176-
key = '-----BEGIN CERTIFICATE-----'
177-
with pytest.raises(JOSEError):
178-
CryptographyRSAKey(key, ALGORITHMS.RS256)
179-
180-
def test_get_public_key(self):
181-
key = CryptographyRSAKey(private_key, ALGORITHMS.RS256)
166+
@pytest.mark.parametrize("Backend", [RSAKey, CryptographyRSAKey])
167+
def test_get_public_key(self, Backend):
168+
key = Backend(private_key, ALGORITHMS.RS256)
182169
public_key = key.public_key()
183170
public_key2 = public_key.public_key()
184171
assert public_key.is_public()
185172
assert public_key2.is_public()
186173
assert public_key == public_key2
187174

188-
key = RSAKey(private_key, ALGORITHMS.RS256)
189-
public_key = key.public_key()
190-
public_key2 = public_key.public_key()
191-
assert public_key.is_public()
192-
assert public_key2.is_public()
193-
assert public_key == public_key2
194-
195-
def test_to_pem(self):
196-
key = CryptographyRSAKey(private_key, ALGORITHMS.RS256)
197-
assert key.to_pem().strip() == private_key.strip()
198-
199-
key = RSAKey(private_key, ALGORITHMS.RS256)
175+
@pytest.mark.parametrize("Backend", [RSAKey, CryptographyRSAKey])
176+
def test_to_pem(self, Backend):
177+
key = Backend(private_key, ALGORITHMS.RS256)
200178
assert key.to_pem().strip() == private_key.strip()
201179

202180
def assert_parameters(self, as_dict, private):
@@ -223,46 +201,38 @@ def assert_parameters(self, as_dict, private):
223201
assert 'dq' not in as_dict
224202
assert 'qi' not in as_dict
225203

226-
def assert_roundtrip(self, key, impl):
227-
assert impl(key.to_dict(), ALGORITHMS.RS256).to_dict() == key.to_dict()
228-
229-
def test_to_dict(self):
230-
key = CryptographyRSAKey(private_key, ALGORITHMS.RS256)
231-
self.assert_parameters(key.to_dict(), private=True)
232-
self.assert_parameters(key.public_key().to_dict(), private=False)
233-
self.assert_roundtrip(key, CryptographyRSAKey)
234-
self.assert_roundtrip(key.public_key(), CryptographyRSAKey)
204+
def assert_roundtrip(self, key, Backend):
205+
assert Backend(
206+
key.to_dict(),
207+
ALGORITHMS.RS256
208+
).to_dict() == key.to_dict()
235209

236-
key = RSAKey(private_key, ALGORITHMS.RS256)
210+
@pytest.mark.parametrize("Backend", [RSAKey, CryptographyRSAKey])
211+
def test_to_dict(self, Backend):
212+
key = Backend(private_key, ALGORITHMS.RS256)
237213
self.assert_parameters(key.to_dict(), private=True)
238214
self.assert_parameters(key.public_key().to_dict(), private=False)
239-
self.assert_roundtrip(key, RSAKey)
240-
self.assert_roundtrip(key.public_key(), RSAKey)
215+
self.assert_roundtrip(key, Backend)
216+
self.assert_roundtrip(key.public_key(), Backend)
241217

242-
def test_signing_parity(self):
243-
key1 = RSAKey(private_key, ALGORITHMS.RS256)
244-
vkey1 = key1.public_key()
245-
key2 = CryptographyRSAKey(private_key, ALGORITHMS.RS256)
246-
vkey2 = key2.public_key()
218+
@pytest.mark.parametrize("BackendSign", [RSAKey, CryptographyRSAKey])
219+
@pytest.mark.parametrize("BackendVerify", [RSAKey, CryptographyRSAKey])
220+
def test_signing_parity(self, BackendSign, BackendVerify):
221+
key_sign = BackendSign(private_key, ALGORITHMS.RS256)
222+
key_verify = BackendVerify(private_key, ALGORITHMS.RS256).public_key()
247223

248224
msg = b'test'
249-
sig1 = key1.sign(msg)
250-
sig2 = key2.sign(msg)
225+
sig = key_sign.sign(msg)
251226

252-
assert vkey1.verify(msg, sig1)
253-
assert vkey1.verify(msg, sig2)
254-
assert vkey2.verify(msg, sig1)
255-
assert vkey2.verify(msg, sig2)
227+
# valid signature
228+
assert key_verify.verify(msg, sig)
256229

257230
# invalid signature
258-
assert not vkey2.verify(msg, b'n' * 64)
231+
assert not key_verify.verify(msg, b'n' * 64)
259232

260-
def test_pycrypto_invalid_signature(self):
233+
@pytest.mark.parametrize("Backend", [RSAKey, CryptographyRSAKey])
234+
def test_pycrypto_unencoded_cleartext(self, Backend):
235+
key = Backend(private_key, ALGORITHMS.RS256)
261236

262-
key = RSAKey(private_key, ALGORITHMS.RS256)
263-
msg = b'test'
264-
signature = key.sign(msg)
265-
public_key = key.public_key()
266-
267-
assert public_key.verify(msg, signature) == True
268-
assert public_key.verify(msg, 1) == False
237+
with pytest.raises(JWKError):
238+
key.sign(True)

0 commit comments

Comments
 (0)