-
Notifications
You must be signed in to change notification settings - Fork 244
/
Copy pathtest_RSA.py
377 lines (324 loc) · 18.4 KB
/
test_RSA.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
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
import base64
import json
try:
from jose.backends import rsa_backend
from jose.backends.rsa_backend import RSAKey as PurePythonRSAKey
except ImportError:
PurePythonRSAKey = rsa_backend = None
try:
from Crypto.PublicKey import RSA as PyCryptoRSA
except ImportError:
PyCryptoRSA = None
try:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa as pyca_rsa
from jose.backends.cryptography_backend import CryptographyRSAKey
except ImportError:
default_backend = pyca_rsa = CryptographyRSAKey = None
import pytest
from jose.backends import RSAKey
from jose.constants import ALGORITHMS
from jose.exceptions import JOSEError, JWKError
private_key_4096_pkcs1 = b"""-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----"""
private_key_2048_pkcs1 = b"""-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAom6GcUPchmHxBuV3zJ60EPC7y30WiiVxn1WXSPHmfqaj0q2U
xS03YugkYmX9lB/EQ6Z5bOY9VuL1oMudL6Dkb9aYYEBZHVgejV7vtYuYT19QMesn
AsmGq8etie7XyWHzfWTxljbF53yvxXJMixcFzebAov9pUiV9Hmy3hYVLw3J1NXVg
gPZpUT2oF+qAayhPsOi2b0CrIE3FvioDx7IiRXKFpV/1gah3NRSKxCrsxV6V+UGO
+trP1ViWiu4oXB5j25kZmkgI0lXG60p58DUUeCOnEemvurltf9T9IEs7LGBEzUYm
itGSY4ZOY3MabPypRfFRRotZEDyZjshq4xfXAwIDAQABAoIBAFclRzoTd4gdmevi
RwDgEKmaDpchGGurpScgC5eWONywWOpaOJwFI1cMRyEHqSHEXU8STMkxSa2I/NF1
DHMWNhkOoBfbzjPhKBse2Sqkp2XGNEdj6z0ik/8rlR6QpvMjezhGZRr7bfhBPCiJ
pylkg7exWp7Yu0/YTyV4nImlNz23GvrYHFtzDzTtn9gW4fe46wI08s4PqH/TyBh8
QkwkTwOKTk6n/xz2hND/shUOGjaoS0o6y4+8v3O1JYUWa7YZaIFofvF/dHR0yieg
2gQjc0c6+VeBm8dEbn3he+KnIBwQbWsiCuWL6Jq4XPtMbqutfovIYf9lRB+3q2PI
VSh3mwECgYEAzhOhG+usoxjJGk2wVJH5wnHL0zyH8gWF4SnnxwwdBOF4kdLB2eva
SJsi8rJQMT0TC4wZ6TsD2fJXGazIyM6OnD+52AViiUsLVS5MR7qEMNitdkWEtDx9
Xve50NF9XkTrn6+cgqvfJ9ezE4cOaiD3Eov1u/HbHRx3K2Qf9IzvGoMCgYEAycgk
yOSYR0A3xKcfCQyOU0THEZWBBzd6zBAQ6VQNbcWHh1E8Ve0td6cvCxfydW1pIzXE
7b7J/BgMoC9oSQPfqQJQF2O0XESrdNgXjscfFpVgPfzbFQNgf7d0DSq4b/A5n5QR
HVMmWzVQoRQUwqTNeVxs0NpY6W6Meqv3i/KJqYECgYA/KyMyhM55fCqA5pmLgueV
Y/5/tMlTNcAxIgBLMnpeuaKUyI7ldveFVBClZmVQgpEo8/wpUw6+Kxvp4d32N+Ld
IGeeQSBQR3Gk3blCL3k/49tgKrUf7n7bsoIB8YVFdUjovRLzty2DcAoTjU2s2IgD
5mUgBGYPCV+6LEnjU6QjcwKBgGg+0FJBVzKoSKd+N5hzNixqwfWhqXFTBkvamQIS
fIWToTsVivhRekXwx2sRyh9EkSaxprW09aEZw5wWIehm6evk1//dcNaiW3oYEcOf
t73xGjGsKnsmrXoOCxSqV3LtRrfcxSLDTHOejbNKLpeIkOb8CvOzem/OvyC5K0DP
4rMBAoGBAJStRo5xQ2F9cyZW8vLd4eR3FHXxF/7Moxr6AyV3RLUjMhkwB8ZcFLUQ
dXI4NN9leDeIpNaGU6ozr+At3f50GtCWxdUppy9FDh5qDamBV8K4/+uNqFPiKFQ9
uwNcJ8daMgVZ0QBrD3CBcSZQrfC484BlV6spJ3C16qDVSQPt7sAI
-----END RSA PRIVATE KEY-----"""
PRIVATE_KEYS = (
pytest.param(private_key_2048_pkcs1, id="RSA_2048_PKCS1"),
pytest.param(private_key_4096_pkcs1, id="RSA_4096_PKCS1"),
)
LEGACY_INVALID_PRIVATE_KEY_PKCS8_PEM = b"""-----BEGIN PRIVATE KEY-----
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
ymbpPjVPxSfCAHJr5Pcu5tuZ0knP
-----END PRIVATE KEY-----
"""
RSA_KW_ALGOS = (
pytest.param(ALGORITHMS.RSA_OAEP, id="RSA_OAEP"),
pytest.param(ALGORITHMS.RSA_OAEP_256, id="RSA_OAEP_256"),
)
def _legacy_invalid_private_key_pkcs8_der():
legacy_key = LEGACY_INVALID_PRIVATE_KEY_PKCS8_PEM.strip()
legacy_key = legacy_key[legacy_key.index(b"\n") : legacy_key.rindex(b"\n")]
return base64.b64decode(legacy_key)
def _actually_invalid_private_key_pkcs8_der():
legacy_key = _legacy_invalid_private_key_pkcs8_der()
invalid_key = legacy_key[: len(rsa_backend.LEGACY_INVALID_PKCS8_RSA_HEADER)]
invalid_key += b"\x00"
invalid_key += legacy_key[len(rsa_backend.LEGACY_INVALID_PKCS8_RSA_HEADER) :]
return invalid_key
def _actually_invalid_private_key_pkcs8_pem():
invalid_key = b"-----BEGIN PRIVATE KEY-----\n"
invalid_key += base64.b64encode(_actually_invalid_private_key_pkcs8_der())
invalid_key += b"\n-----END PRIVATE KEY-----\n"
return invalid_key
@pytest.mark.skipif(PurePythonRSAKey is None, reason="python-rsa backend not available")
class TestPurePythonRsa:
def test_python_rsa_legacy_pem_read(self):
key = PurePythonRSAKey(LEGACY_INVALID_PRIVATE_KEY_PKCS8_PEM, ALGORITHMS.RS256)
new_pem = key.to_pem(pem_format="PKCS8")
assert new_pem != LEGACY_INVALID_PRIVATE_KEY_PKCS8_PEM
def test_python_rsa_legacy_pem_invalid(self):
with pytest.raises(JWKError) as excinfo:
PurePythonRSAKey(_actually_invalid_private_key_pkcs8_pem(), ALGORITHMS.RS256)
excinfo.match("Invalid private key encoding")
def test_python_rsa_legacy_private_key_pkcs8_to_pkcs1(self):
legacy_key = _legacy_invalid_private_key_pkcs8_der()
legacy_pkcs1 = legacy_key[len(rsa_backend.LEGACY_INVALID_PKCS8_RSA_HEADER) :]
assert rsa_backend._legacy_private_key_pkcs8_to_pkcs1(legacy_key) == legacy_pkcs1
def test_python_rsa_legacy_private_key_pkcs8_to_pkcs1_invalid(self):
invalid_key = _actually_invalid_private_key_pkcs8_der()
with pytest.raises(ValueError) as excinfo:
rsa_backend._legacy_private_key_pkcs8_to_pkcs1(invalid_key)
excinfo.match("Invalid private key encoding")
@pytest.mark.cryptography
@pytest.mark.skipif(
None in (default_backend, pyca_rsa, CryptographyRSAKey), reason="Cryptography backend not available"
)
def test_cryptography_RSA_key_instance():
key = pyca_rsa.RSAPublicNumbers(
int(65537),
int(
26057131595212989515105618545799160306093557851986992545257129318694524535510983041068168825614868056510242030438003863929818932202262132630250203397069801217463517914103389095129323580576852108653940669240896817348477800490303630912852266209307160550655497615975529276169196271699168537716821419779900117025818140018436554173242441334827711966499484119233207097432165756707507563413323850255548329534279691658369466534587631102538061857114141268972476680597988266772849780811214198186940677291891818952682545840788356616771009013059992237747149380197028452160324144544057074406611859615973035412993832273216732343819
),
).public_key(default_backend())
pubkey = CryptographyRSAKey(key, ALGORITHMS.RS256)
assert pubkey.is_public()
pem = pubkey.to_pem()
assert pem.startswith(b"-----BEGIN PUBLIC KEY-----")
@pytest.mark.cryptography
@pytest.mark.parametrize("private_key_pem", PRIVATE_KEYS)
@pytest.mark.parametrize("algorithm", RSA_KW_ALGOS)
@pytest.mark.skipif(
None in (default_backend, pyca_rsa, CryptographyRSAKey), reason="Cryptography backend not available"
)
def test_cryptography_wrap_key_unencoded_cleartext(private_key_pem, algorithm):
private_key = CryptographyRSAKey(private_key_pem, algorithm)
key = b"test"
public_key = private_key.public_key()
wrapped = public_key.wrap_key(key)
unwrapped = private_key.unwrap_key(wrapped)
assert unwrapped == key
@pytest.mark.skipif(RSAKey is None, reason="RSA is not available")
class TestRSAAlgorithm:
def test_RSA_key(self):
assert not RSAKey(private_key_4096_pkcs1, ALGORITHMS.RS256).is_public()
def test_string_secret(self):
key = "secret"
with pytest.raises(JOSEError):
RSAKey(key, ALGORITHMS.RS256)
def test_object(self):
key = object()
with pytest.raises(JOSEError):
RSAKey(key, ALGORITHMS.RS256)
def test_bad_cert(
self,
):
key = "-----BEGIN CERTIFICATE-----"
with pytest.raises(JOSEError):
RSAKey(key, ALGORITHMS.RS256)
def test_invalid_algorithm(self):
with pytest.raises(JWKError):
RSAKey(private_key_4096_pkcs1, ALGORITHMS.ES256)
with pytest.raises(JWKError):
RSAKey({"kty": "bla"}, ALGORITHMS.RS256)
def test_RSA_jwk(self):
key = {
"kty": "RSA",
"n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
"e": "AQAB",
}
assert RSAKey(key, ALGORITHMS.RS256).is_public()
key = {
"kty": "RSA",
"kid": "[email protected]",
"use": "sig",
"n": "n4EPtAOCc9AlkeQHPzHStgAbgs7bTZLwUBZdR8_KuKPEHLd4rHVTeT-O-XV2jRojdNhxJWTDvNd7nqQ0VEiZQHz_AJmSCpMaJMRBSFKrKb2wqVwGU_NsYOYL-QtiWN2lbzcEe6XC0dApr5ydQLrHqkHHig3RBordaZ6Aj-oBHqFEHYpPe7Tpe-OfVfHd1E6cS6M1FZcD1NNLYD5lFHpPI9bTwJlsde3uhGqC0ZCuEHg8lhzwOHrtIQbS0FVbb9k3-tVTU4fg_3L_vniUFAKwuCLqKnS2BYwdq_mzSnbLY7h_qixoR7jig3__kRhuaxwUkRz5iaiQkqgc5gHdrNP5zw",
"e": "AQAB",
"d": "bWUC9B-EFRIo8kpGfh0ZuyGPvMNKvYWNtB_ikiH9k20eT-O1q_I78eiZkpXxXQ0UTEs2LsNRS-8uJbvQ-A1irkwMSMkK1J3XTGgdrhCku9gRldY7sNA_AKZGh-Q661_42rINLRCe8W-nZ34ui_qOfkLnK9QWDDqpaIsA-bMwWWSDFu2MUBYwkHTMEzLYGqOe04noqeq1hExBTHBOBdkMXiuFhUq1BU6l-DqEiWxqg82sXt2h-LMnT3046AOYJoRioz75tSUQfGCshWTBnP5uDjd18kKhyv07lhfSJdrPdM5Plyl21hsFf4L_mHCuoFau7gdsPfHPxxjVOcOpBrQzwQ",
"p": "3Slxg_DwTXJcb6095RoXygQCAZ5RnAvZlno1yhHtnUex_fp7AZ_9nRaO7HX_-SFfGQeutao2TDjDAWU4Vupk8rw9JR0AzZ0N2fvuIAmr_WCsmGpeNqQnev1T7IyEsnh8UMt-n5CafhkikzhEsrmndH6LxOrvRJlsPp6Zv8bUq0k",
"q": "uKE2dh-cTf6ERF4k4e_jy78GfPYUIaUyoSSJuBzp3Cubk3OCqs6grT8bR_cu0Dm1MZwWmtdqDyI95HrUeq3MP15vMMON8lHTeZu2lmKvwqW7anV5UzhM1iZ7z4yMkuUwFWoBvyY898EXvRD-hdqRxHlSqAZ192zB3pVFJ0s7pFc",
"dp": "B8PVvXkvJrj2L-GYQ7v3y9r6Kw5g9SahXBwsWUzp19TVlgI-YV85q1NIb1rxQtD-IsXXR3-TanevuRPRt5OBOdiMGQp8pbt26gljYfKU_E9xn-RULHz0-ed9E9gXLKD4VGngpz-PfQ_q29pk5xWHoJp009Qf1HvChixRX 59ehik",
"dq": "CLDmDGduhylc9o7r84rEUVn7pzQ6PF83Y-iBZx5NT-TpnOZKF1pErAMVeKzFEl41DlHHqqBLSM0W1sOFbwTxYWZDm6sI6og5iTbwQGIC3gnJKbi_7k_vJgGHwHxgPaX2PnvP-zyEkDERuf-ry4c_Z11Cq9AqC2yeL6kdKT1cYF8",
"qi": "3PiqvXQN0zwMeE-sBvZgi289XP9XCQF3VWqPzMKnIgQp7_Tugo6-NZBKCQsMf3HaEGBjTVJs_jcK8-TRXvaKe-7ZMaQj8VfBdYkssbu0NKDDhjJ-GtiseaDVWt7dcH0cfwxgFUHpQh7FoCrjFJ6h6ZEpMF6xmujs4qMpPz8aaI4",
}
assert not RSAKey(key, ALGORITHMS.RS256).is_public()
del key["p"]
# Some but not all extra parameters are present
with pytest.raises(JWKError):
RSAKey(key, ALGORITHMS.RS256)
del key["q"]
del key["dp"]
del key["dq"]
del key["qi"]
# None of the extra parameters are present, but 'key' is still private.
assert not RSAKey(key, ALGORITHMS.RS256).is_public()
@pytest.mark.parametrize("private_key", PRIVATE_KEYS)
def test_get_public_key(self, private_key):
key = RSAKey(private_key, ALGORITHMS.RS256)
public_key = key.public_key()
public_key2 = public_key.public_key()
assert public_key.is_public()
assert public_key2.is_public()
assert public_key == public_key2
@pytest.mark.parametrize("pkey", PRIVATE_KEYS)
def test_to_pem(self, pkey):
key = RSAKey(pkey, ALGORITHMS.RS256)
assert key.to_pem(pem_format="PKCS1").strip() == pkey.strip()
pkcs8 = key.to_pem(pem_format="PKCS8").strip()
assert pkcs8 != pkey.strip()
newkey = RSAKey(pkcs8, ALGORITHMS.RS256)
assert newkey.to_pem(pem_format="PKCS1").strip() == pkey.strip()
def assert_parameters(self, as_dict, private):
assert isinstance(as_dict, dict)
# Public parameters should always be there.
assert "n" in as_dict
assert "e" in as_dict
if private:
# Private parameters as well
assert "d" in as_dict
assert "p" in as_dict
assert "q" in as_dict
assert "dp" in as_dict
assert "dq" in as_dict
assert "qi" in as_dict
else:
# Private parameters should be absent
assert "d" not in as_dict
assert "p" not in as_dict
assert "q" not in as_dict
assert "dp" not in as_dict
assert "dq" not in as_dict
assert "qi" not in as_dict
# as_dict should be serializable to JSON
json.dumps(as_dict)
def assert_roundtrip(self, key):
assert RSAKey(key.to_dict(), ALGORITHMS.RS256).to_dict() == key.to_dict()
@pytest.mark.parametrize("private_key", PRIVATE_KEYS)
def test_to_dict(self, private_key):
key = RSAKey(private_key, ALGORITHMS.RS256)
self.assert_parameters(key.to_dict(), private=True)
self.assert_parameters(key.public_key().to_dict(), private=False)
self.assert_roundtrip(key)
self.assert_roundtrip(key.public_key())