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 9import struct 10 11import pytest 12 13from cryptography.hazmat.backends.interfaces import CipherBackend 14from cryptography.hazmat.primitives.ciphers import Cipher, algorithms 15 16from .utils import _load_all_params 17from ...utils import load_nist_vectors 18 19 20@pytest.mark.supported( 21 only_if=lambda backend: backend.cipher_supported( 22 algorithms.ChaCha20(b"\x00" * 32, b"0" * 16), None 23 ), 24 skip_message="Does not support ChaCha20", 25) 26@pytest.mark.requires_backend_interface(interface=CipherBackend) 27class TestChaCha20(object): 28 @pytest.mark.parametrize( 29 "vector", 30 _load_all_params( 31 os.path.join("ciphers", "ChaCha20"), 32 ["rfc7539.txt"], 33 load_nist_vectors, 34 ), 35 ) 36 def test_vectors(self, vector, backend): 37 key = binascii.unhexlify(vector["key"]) 38 nonce = binascii.unhexlify(vector["nonce"]) 39 ibc = struct.pack("<i", int(vector["initial_block_counter"])) 40 pt = binascii.unhexlify(vector["plaintext"]) 41 encryptor = Cipher( 42 algorithms.ChaCha20(key, ibc + nonce), None, backend 43 ).encryptor() 44 computed_ct = encryptor.update(pt) + encryptor.finalize() 45 assert binascii.hexlify(computed_ct) == vector["ciphertext"] 46 47 def test_buffer_protocol(self, backend): 48 key = bytearray(os.urandom(32)) 49 nonce = bytearray(os.urandom(16)) 50 cipher = Cipher(algorithms.ChaCha20(key, nonce), None, backend) 51 enc = cipher.encryptor() 52 ct = enc.update(bytearray(b"hello")) + enc.finalize() 53 dec = cipher.decryptor() 54 pt = dec.update(ct) + dec.finalize() 55 assert pt == b"hello" 56 57 def test_key_size(self): 58 chacha = algorithms.ChaCha20(b"0" * 32, b"0" * 16) 59 assert chacha.key_size == 256 60 61 def test_invalid_key_size(self): 62 with pytest.raises(ValueError): 63 algorithms.ChaCha20(b"wrongsize", b"0" * 16) 64 65 def test_invalid_nonce(self): 66 with pytest.raises(ValueError): 67 algorithms.ChaCha20(b"0" * 32, b"0") 68 69 with pytest.raises(TypeError): 70 algorithms.ChaCha20(b"0" * 32, object()) 71 72 def test_invalid_key_type(self): 73 with pytest.raises(TypeError, match="key must be bytes"): 74 algorithms.ChaCha20(u"0" * 32, b"0" * 16) 75