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
8import os
9
10import pytest
11
12from cryptography.hazmat.backends.interfaces import HashBackend
13from cryptography.hazmat.primitives import hashes
14
15from .utils import _load_all_params, generate_hash_test
16from ...utils import load_hash_vectors, load_nist_vectors
17
18
19@pytest.mark.supported(
20    only_if=lambda backend: backend.hash_supported(hashes.SHA1()),
21    skip_message="Does not support SHA1",
22)
23@pytest.mark.requires_backend_interface(interface=HashBackend)
24class TestSHA1(object):
25    test_sha1 = generate_hash_test(
26        load_hash_vectors,
27        os.path.join("hashes", "SHA1"),
28        ["SHA1LongMsg.rsp", "SHA1ShortMsg.rsp"],
29        hashes.SHA1(),
30    )
31
32
33@pytest.mark.supported(
34    only_if=lambda backend: backend.hash_supported(hashes.SHA224()),
35    skip_message="Does not support SHA224",
36)
37@pytest.mark.requires_backend_interface(interface=HashBackend)
38class TestSHA224(object):
39    test_sha224 = generate_hash_test(
40        load_hash_vectors,
41        os.path.join("hashes", "SHA2"),
42        ["SHA224LongMsg.rsp", "SHA224ShortMsg.rsp"],
43        hashes.SHA224(),
44    )
45
46
47@pytest.mark.supported(
48    only_if=lambda backend: backend.hash_supported(hashes.SHA256()),
49    skip_message="Does not support SHA256",
50)
51@pytest.mark.requires_backend_interface(interface=HashBackend)
52class TestSHA256(object):
53    test_sha256 = generate_hash_test(
54        load_hash_vectors,
55        os.path.join("hashes", "SHA2"),
56        ["SHA256LongMsg.rsp", "SHA256ShortMsg.rsp"],
57        hashes.SHA256(),
58    )
59
60
61@pytest.mark.supported(
62    only_if=lambda backend: backend.hash_supported(hashes.SHA384()),
63    skip_message="Does not support SHA384",
64)
65@pytest.mark.requires_backend_interface(interface=HashBackend)
66class TestSHA384(object):
67    test_sha384 = generate_hash_test(
68        load_hash_vectors,
69        os.path.join("hashes", "SHA2"),
70        ["SHA384LongMsg.rsp", "SHA384ShortMsg.rsp"],
71        hashes.SHA384(),
72    )
73
74
75@pytest.mark.supported(
76    only_if=lambda backend: backend.hash_supported(hashes.SHA512()),
77    skip_message="Does not support SHA512",
78)
79@pytest.mark.requires_backend_interface(interface=HashBackend)
80class TestSHA512(object):
81    test_sha512 = generate_hash_test(
82        load_hash_vectors,
83        os.path.join("hashes", "SHA2"),
84        ["SHA512LongMsg.rsp", "SHA512ShortMsg.rsp"],
85        hashes.SHA512(),
86    )
87
88
89@pytest.mark.supported(
90    only_if=lambda backend: backend.hash_supported(hashes.SHA512_224()),
91    skip_message="Does not support SHA512/224",
92)
93@pytest.mark.requires_backend_interface(interface=HashBackend)
94class TestSHA512224(object):
95    test_sha512_224 = generate_hash_test(
96        load_hash_vectors,
97        os.path.join("hashes", "SHA2"),
98        ["SHA512_224LongMsg.rsp", "SHA512_224ShortMsg.rsp"],
99        hashes.SHA512_224(),
100    )
101
102
103@pytest.mark.supported(
104    only_if=lambda backend: backend.hash_supported(hashes.SHA512_256()),
105    skip_message="Does not support SHA512/256",
106)
107@pytest.mark.requires_backend_interface(interface=HashBackend)
108class TestSHA512256(object):
109    test_sha512_256 = generate_hash_test(
110        load_hash_vectors,
111        os.path.join("hashes", "SHA2"),
112        ["SHA512_256LongMsg.rsp", "SHA512_256ShortMsg.rsp"],
113        hashes.SHA512_256(),
114    )
115
116
117@pytest.mark.supported(
118    only_if=lambda backend: backend.hash_supported(hashes.MD5()),
119    skip_message="Does not support MD5",
120)
121@pytest.mark.requires_backend_interface(interface=HashBackend)
122class TestMD5(object):
123    test_md5 = generate_hash_test(
124        load_hash_vectors,
125        os.path.join("hashes", "MD5"),
126        ["rfc-1321.txt"],
127        hashes.MD5(),
128    )
129
130
131@pytest.mark.supported(
132    only_if=lambda backend: backend.hash_supported(
133        hashes.BLAKE2b(digest_size=64)
134    ),
135    skip_message="Does not support BLAKE2b",
136)
137@pytest.mark.requires_backend_interface(interface=HashBackend)
138class TestBLAKE2b(object):
139    test_b2b = generate_hash_test(
140        load_hash_vectors,
141        os.path.join("hashes", "blake2"),
142        ["blake2b.txt"],
143        hashes.BLAKE2b(digest_size=64),
144    )
145
146
147@pytest.mark.supported(
148    only_if=lambda backend: backend.hash_supported(
149        hashes.BLAKE2s(digest_size=32)
150    ),
151    skip_message="Does not support BLAKE2s",
152)
153@pytest.mark.requires_backend_interface(interface=HashBackend)
154class TestBLAKE2s256(object):
155    test_b2s = generate_hash_test(
156        load_hash_vectors,
157        os.path.join("hashes", "blake2"),
158        ["blake2s.txt"],
159        hashes.BLAKE2s(digest_size=32),
160    )
161
162
163@pytest.mark.supported(
164    only_if=lambda backend: backend.hash_supported(hashes.SHA3_224()),
165    skip_message="Does not support SHA3_224",
166)
167@pytest.mark.requires_backend_interface(interface=HashBackend)
168class TestSHA3224(object):
169    test_sha3_224 = generate_hash_test(
170        load_hash_vectors,
171        os.path.join("hashes", "SHA3"),
172        ["SHA3_224LongMsg.rsp", "SHA3_224ShortMsg.rsp"],
173        hashes.SHA3_224(),
174    )
175
176
177@pytest.mark.supported(
178    only_if=lambda backend: backend.hash_supported(hashes.SHA3_256()),
179    skip_message="Does not support SHA3_256",
180)
181@pytest.mark.requires_backend_interface(interface=HashBackend)
182class TestSHA3256(object):
183    test_sha3_256 = generate_hash_test(
184        load_hash_vectors,
185        os.path.join("hashes", "SHA3"),
186        ["SHA3_256LongMsg.rsp", "SHA3_256ShortMsg.rsp"],
187        hashes.SHA3_256(),
188    )
189
190
191@pytest.mark.supported(
192    only_if=lambda backend: backend.hash_supported(hashes.SHA3_384()),
193    skip_message="Does not support SHA3_384",
194)
195@pytest.mark.requires_backend_interface(interface=HashBackend)
196class TestSHA3384(object):
197    test_sha3_384 = generate_hash_test(
198        load_hash_vectors,
199        os.path.join("hashes", "SHA3"),
200        ["SHA3_384LongMsg.rsp", "SHA3_384ShortMsg.rsp"],
201        hashes.SHA3_384(),
202    )
203
204
205@pytest.mark.supported(
206    only_if=lambda backend: backend.hash_supported(hashes.SHA3_512()),
207    skip_message="Does not support SHA3_512",
208)
209@pytest.mark.requires_backend_interface(interface=HashBackend)
210class TestSHA3512(object):
211    test_sha3_512 = generate_hash_test(
212        load_hash_vectors,
213        os.path.join("hashes", "SHA3"),
214        ["SHA3_512LongMsg.rsp", "SHA3_512ShortMsg.rsp"],
215        hashes.SHA3_512(),
216    )
217
218
219@pytest.mark.supported(
220    only_if=lambda backend: backend.hash_supported(
221        hashes.SHAKE128(digest_size=16)
222    ),
223    skip_message="Does not support SHAKE128",
224)
225@pytest.mark.requires_backend_interface(interface=HashBackend)
226class TestSHAKE128(object):
227    test_shake128 = generate_hash_test(
228        load_hash_vectors,
229        os.path.join("hashes", "SHAKE"),
230        ["SHAKE128LongMsg.rsp", "SHAKE128ShortMsg.rsp"],
231        hashes.SHAKE128(digest_size=16),
232    )
233
234    @pytest.mark.parametrize(
235        "vector",
236        _load_all_params(
237            os.path.join("hashes", "SHAKE"),
238            ["SHAKE128VariableOut.rsp"],
239            load_nist_vectors,
240        ),
241    )
242    def test_shake128_variable(self, vector, backend):
243        output_length = int(vector["outputlen"]) // 8
244        msg = binascii.unhexlify(vector["msg"])
245        shake = hashes.SHAKE128(digest_size=output_length)
246        m = hashes.Hash(shake, backend=backend)
247        m.update(msg)
248        assert m.finalize() == binascii.unhexlify(vector["output"])
249
250
251@pytest.mark.supported(
252    only_if=lambda backend: backend.hash_supported(
253        hashes.SHAKE256(digest_size=32)
254    ),
255    skip_message="Does not support SHAKE256",
256)
257@pytest.mark.requires_backend_interface(interface=HashBackend)
258class TestSHAKE256(object):
259    test_shake256 = generate_hash_test(
260        load_hash_vectors,
261        os.path.join("hashes", "SHAKE"),
262        ["SHAKE256LongMsg.rsp", "SHAKE256ShortMsg.rsp"],
263        hashes.SHAKE256(digest_size=32),
264    )
265
266    @pytest.mark.parametrize(
267        "vector",
268        _load_all_params(
269            os.path.join("hashes", "SHAKE"),
270            ["SHAKE256VariableOut.rsp"],
271            load_nist_vectors,
272        ),
273    )
274    def test_shake256_variable(self, vector, backend):
275        output_length = int(vector["outputlen"]) // 8
276        msg = binascii.unhexlify(vector["msg"])
277        shake = hashes.SHAKE256(digest_size=output_length)
278        m = hashes.Hash(shake, backend=backend)
279        m.update(msg)
280        assert m.finalize() == binascii.unhexlify(vector["output"])
281