| # This file is dual licensed under the terms of the Apache License, Version |
| # 2.0, and the BSD License. See the LICENSE file in the root of this repository |
| # for complete details. |
| |
| from __future__ import absolute_import, division, print_function |
| |
| import binascii |
| import os |
| import struct |
| |
| import pytest |
| |
| from cryptography.hazmat.backends.interfaces import CipherBackend |
| from cryptography.hazmat.primitives.ciphers import Cipher, algorithms |
| |
| from .utils import _load_all_params |
| from ...utils import load_nist_vectors |
| |
| |
| @pytest.mark.supported( |
| only_if=lambda backend: backend.cipher_supported( |
| algorithms.ChaCha20(b"\x00" * 32, b"0" * 16), None |
| ), |
| skip_message="Does not support ChaCha20", |
| ) |
| @pytest.mark.requires_backend_interface(interface=CipherBackend) |
| class TestChaCha20(object): |
| @pytest.mark.parametrize( |
| "vector", |
| _load_all_params( |
| os.path.join("ciphers", "ChaCha20"), |
| ["rfc7539.txt"], |
| load_nist_vectors |
| ) |
| ) |
| def test_vectors(self, vector, backend): |
| key = binascii.unhexlify(vector["key"]) |
| nonce = binascii.unhexlify(vector["nonce"]) |
| ibc = struct.pack("<i", int(vector["initial_block_counter"])) |
| pt = binascii.unhexlify(vector["plaintext"]) |
| encryptor = Cipher( |
| algorithms.ChaCha20(key, ibc + nonce), None, backend |
| ).encryptor() |
| computed_ct = encryptor.update(pt) + encryptor.finalize() |
| assert binascii.hexlify(computed_ct) == vector["ciphertext"] |
| |
| def test_buffer_protocol(self, backend): |
| key = bytearray(os.urandom(32)) |
| nonce = bytearray(os.urandom(16)) |
| cipher = Cipher( |
| algorithms.ChaCha20(key, nonce), None, backend |
| ) |
| enc = cipher.encryptor() |
| ct = enc.update(bytearray(b"hello")) + enc.finalize() |
| dec = cipher.decryptor() |
| pt = dec.update(ct) + dec.finalize() |
| assert pt == b"hello" |
| |
| def test_key_size(self): |
| chacha = algorithms.ChaCha20(b"0" * 32, b"0" * 16) |
| assert chacha.key_size == 256 |
| |
| def test_invalid_key_size(self): |
| with pytest.raises(ValueError): |
| algorithms.ChaCha20(b"wrongsize", b"0" * 16) |
| |
| def test_invalid_nonce(self): |
| with pytest.raises(ValueError): |
| algorithms.ChaCha20(b"0" * 32, b"0") |
| |
| with pytest.raises(TypeError): |
| algorithms.ChaCha20(b"0" * 32, object()) |
| |
| def test_invalid_key_type(self): |
| with pytest.raises(TypeError, match="key must be bytes"): |
| algorithms.ChaCha20(u"0" * 32, b"0" * 16) |