• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# This file is dual licensed under the terms of the Apache License, Version
2# 2.0, and the BSD License. See the LICENSE file in the root of this repository
3# for complete details.
4
5from __future__ import absolute_import, division, print_function
6
7import binascii
8
9import pytest
10
11from cryptography.exceptions import InvalidSignature
12from cryptography.hazmat.backends.interfaces import RSABackend
13from cryptography.hazmat.primitives import hashes, serialization
14from cryptography.hazmat.primitives.asymmetric import padding
15
16
17_DIGESTS = {
18    "SHA-1": hashes.SHA1(),
19    "SHA-224": hashes.SHA224(),
20    "SHA-256": hashes.SHA256(),
21    "SHA-384": hashes.SHA384(),
22    "SHA-512": hashes.SHA512(),
23    # Not supported by OpenSSL for RSA signing
24    "SHA-512/224": None,
25    "SHA-512/256": None,
26    "SHA3-224": hashes.SHA3_224(),
27    "SHA3-256": hashes.SHA3_256(),
28    "SHA3-384": hashes.SHA3_384(),
29    "SHA3-512": hashes.SHA3_512(),
30}
31
32
33def should_verify(backend, wycheproof):
34    if wycheproof.valid:
35        return True
36
37    if wycheproof.acceptable:
38        return not wycheproof.has_flag("MissingNull")
39
40    return False
41
42
43@pytest.mark.requires_backend_interface(interface=RSABackend)
44@pytest.mark.wycheproof_tests(
45    "rsa_signature_test.json",
46    "rsa_signature_2048_sha224_test.json",
47    "rsa_signature_2048_sha256_test.json",
48    "rsa_signature_2048_sha384_test.json",
49    "rsa_signature_2048_sha512_test.json",
50    "rsa_signature_2048_sha512_224_test.json",
51    "rsa_signature_2048_sha512_256_test.json",
52    "rsa_signature_2048_sha3_224_test.json",
53    "rsa_signature_2048_sha3_256_test.json",
54    "rsa_signature_2048_sha3_384_test.json",
55    "rsa_signature_2048_sha3_512_test.json",
56    "rsa_signature_3072_sha256_test.json",
57    "rsa_signature_3072_sha384_test.json",
58    "rsa_signature_3072_sha512_test.json",
59    "rsa_signature_3072_sha512_256_test.json",
60    "rsa_signature_3072_sha3_256_test.json",
61    "rsa_signature_3072_sha3_384_test.json",
62    "rsa_signature_3072_sha3_512_test.json",
63    "rsa_signature_4096_sha384_test.json",
64    "rsa_signature_4096_sha512_test.json",
65    "rsa_signature_4096_sha512_256_test.json",
66)
67def test_rsa_pkcs1v15_signature(backend, wycheproof):
68    key = serialization.load_der_public_key(
69        binascii.unhexlify(wycheproof.testgroup["keyDer"]), backend
70    )
71    digest = _DIGESTS[wycheproof.testgroup["sha"]]
72
73    if digest is None or not backend.hash_supported(digest):
74        pytest.skip(
75            "Hash {} not supported".format(wycheproof.testgroup["sha"])
76        )
77
78    if should_verify(backend, wycheproof):
79        key.verify(
80            binascii.unhexlify(wycheproof.testcase["sig"]),
81            binascii.unhexlify(wycheproof.testcase["msg"]),
82            padding.PKCS1v15(),
83            digest,
84        )
85    else:
86        with pytest.raises(InvalidSignature):
87            key.verify(
88                binascii.unhexlify(wycheproof.testcase["sig"]),
89                binascii.unhexlify(wycheproof.testcase["msg"]),
90                padding.PKCS1v15(),
91                digest,
92            )
93
94
95@pytest.mark.wycheproof_tests("rsa_sig_gen_misc_test.json")
96def test_rsa_pkcs1v15_signature_generation(backend, wycheproof):
97    key = serialization.load_pem_private_key(
98        wycheproof.testgroup["privateKeyPem"].encode(),
99        password=None,
100        backend=backend,
101    )
102    digest = _DIGESTS[wycheproof.testgroup["sha"]]
103
104    sig = key.sign(
105        binascii.unhexlify(wycheproof.testcase["msg"]),
106        padding.PKCS1v15(),
107        digest,
108    )
109    assert sig == binascii.unhexlify(wycheproof.testcase["sig"])
110
111
112@pytest.mark.requires_backend_interface(interface=RSABackend)
113@pytest.mark.wycheproof_tests(
114    "rsa_pss_2048_sha1_mgf1_20_test.json",
115    "rsa_pss_2048_sha256_mgf1_0_test.json",
116    "rsa_pss_2048_sha256_mgf1_32_test.json",
117    "rsa_pss_2048_sha512_256_mgf1_28_test.json",
118    "rsa_pss_2048_sha512_256_mgf1_32_test.json",
119    "rsa_pss_3072_sha256_mgf1_32_test.json",
120    "rsa_pss_4096_sha256_mgf1_32_test.json",
121    "rsa_pss_4096_sha512_mgf1_32_test.json",
122    "rsa_pss_misc_test.json",
123)
124def test_rsa_pss_signature(backend, wycheproof):
125    key = serialization.load_der_public_key(
126        binascii.unhexlify(wycheproof.testgroup["keyDer"]), backend
127    )
128    digest = _DIGESTS[wycheproof.testgroup["sha"]]
129    mgf_digest = _DIGESTS[wycheproof.testgroup["mgfSha"]]
130
131    if digest is None or mgf_digest is None:
132        pytest.skip(
133            "PSS with digest={} and MGF digest={} not supported".format(
134                wycheproof.testgroup["sha"],
135                wycheproof.testgroup["mgfSha"],
136            )
137        )
138
139    if wycheproof.valid or wycheproof.acceptable:
140        key.verify(
141            binascii.unhexlify(wycheproof.testcase["sig"]),
142            binascii.unhexlify(wycheproof.testcase["msg"]),
143            padding.PSS(
144                mgf=padding.MGF1(mgf_digest),
145                salt_length=wycheproof.testgroup["sLen"],
146            ),
147            digest,
148        )
149    else:
150        with pytest.raises(InvalidSignature):
151            key.verify(
152                binascii.unhexlify(wycheproof.testcase["sig"]),
153                binascii.unhexlify(wycheproof.testcase["msg"]),
154                padding.PSS(
155                    mgf=padding.MGF1(mgf_digest),
156                    salt_length=wycheproof.testgroup["sLen"],
157                ),
158                digest,
159            )
160
161
162@pytest.mark.requires_backend_interface(interface=RSABackend)
163@pytest.mark.wycheproof_tests(
164    "rsa_oaep_2048_sha1_mgf1sha1_test.json",
165    "rsa_oaep_2048_sha224_mgf1sha1_test.json",
166    "rsa_oaep_2048_sha224_mgf1sha224_test.json",
167    "rsa_oaep_2048_sha256_mgf1sha1_test.json",
168    "rsa_oaep_2048_sha256_mgf1sha256_test.json",
169    "rsa_oaep_2048_sha384_mgf1sha1_test.json",
170    "rsa_oaep_2048_sha384_mgf1sha384_test.json",
171    "rsa_oaep_2048_sha512_mgf1sha1_test.json",
172    "rsa_oaep_2048_sha512_mgf1sha512_test.json",
173    "rsa_oaep_3072_sha256_mgf1sha1_test.json",
174    "rsa_oaep_3072_sha256_mgf1sha256_test.json",
175    "rsa_oaep_3072_sha512_mgf1sha1_test.json",
176    "rsa_oaep_3072_sha512_mgf1sha512_test.json",
177    "rsa_oaep_4096_sha256_mgf1sha1_test.json",
178    "rsa_oaep_4096_sha256_mgf1sha256_test.json",
179    "rsa_oaep_4096_sha512_mgf1sha1_test.json",
180    "rsa_oaep_4096_sha512_mgf1sha512_test.json",
181    "rsa_oaep_misc_test.json",
182)
183def test_rsa_oaep_encryption(backend, wycheproof):
184    key = serialization.load_pem_private_key(
185        wycheproof.testgroup["privateKeyPem"].encode("ascii"),
186        password=None,
187        backend=backend,
188    )
189    digest = _DIGESTS[wycheproof.testgroup["sha"]]
190    mgf_digest = _DIGESTS[wycheproof.testgroup["mgfSha"]]
191
192    padding_algo = padding.OAEP(
193        mgf=padding.MGF1(algorithm=mgf_digest),
194        algorithm=digest,
195        label=binascii.unhexlify(wycheproof.testcase["label"]),
196    )
197
198    if not backend.rsa_padding_supported(padding_algo):
199        pytest.skip(
200            "OAEP with digest={} and MGF digest={} not supported".format(
201                wycheproof.testgroup["sha"],
202                wycheproof.testgroup["mgfSha"],
203            )
204        )
205
206    if wycheproof.valid or wycheproof.acceptable:
207        pt = key.decrypt(
208            binascii.unhexlify(wycheproof.testcase["ct"]), padding_algo
209        )
210        assert pt == binascii.unhexlify(wycheproof.testcase["msg"])
211    else:
212        with pytest.raises(ValueError):
213            key.decrypt(
214                binascii.unhexlify(wycheproof.testcase["ct"]), padding_algo
215            )
216
217
218@pytest.mark.wycheproof_tests(
219    "rsa_pkcs1_2048_test.json",
220    "rsa_pkcs1_3072_test.json",
221    "rsa_pkcs1_4096_test.json",
222)
223def test_rsa_pkcs1_encryption(backend, wycheproof):
224    key = serialization.load_pem_private_key(
225        wycheproof.testgroup["privateKeyPem"].encode("ascii"),
226        password=None,
227        backend=backend,
228    )
229
230    if wycheproof.valid:
231        pt = key.decrypt(
232            binascii.unhexlify(wycheproof.testcase["ct"]), padding.PKCS1v15()
233        )
234        assert pt == binascii.unhexlify(wycheproof.testcase["msg"])
235    else:
236        with pytest.raises(ValueError):
237            key.decrypt(
238                binascii.unhexlify(wycheproof.testcase["ct"]),
239                padding.PKCS1v15(),
240            )
241