ChaCha20¶
How to use the crypto_condor.primitives.ChaCha20 module to test implementations
of ChaCha20.
Supported parameters¶
There are two supported modes of operation: ChaCha20 on its own and the construction
with Poly1305. They are defined by the Mode enum.
Two operations can be performed: ENCRYPT and
DECRYPT. These are defined by the Operation enum.
Test an implementation directly¶
- crypto_condor.primitives.ChaCha20.test(encrypt, decrypt, mode, *, resilience=True)¶
- Tests an implementation of ChaCha20(-Poly1305) encryption and decryption. - It runs test vectors on the given functions. These functions must conform to the - Encryptand- Decryptprotocols.- Parameters:
- Keyword Arguments:
- resilience – If True, runs Wycheproof test vectors. 
- Returns:
- A dictionary of results. - If resilience is True, Wycheproof vectors are used. The results are indexed by - ChaCha20/test_wycheproof_[encrypt/decrypt]/[mode].
- Return type:
 - Example - Let’s test PyCryptodome’s implementation of ChaCha20. - We start by importing the ChaCha20 modules of crypto-condor and PyCryptodome. - >>> from crypto_condor.primitives import ChaCha20 >>> from Crypto.Cipher import ChaCha20 as pyChaCha20 - We need to wrap PyCryptodome’s to match the signature of - Encryptand- Decrypt. In both cases we want to match the first overload, as it is the one that corresponds to ChaCha20.- >>> def my_enc( ... key: bytes, ... plaintext: bytes, ... nonce: bytes, ... *, ... init_counter: int = 0 ... ) -> bytes: ... cipher = pyChaCha20.new(key=key, nonce=nonce) ... if init_counter > 0: ... cipher.seek(64 * init_counter) ... return cipher.encrypt(plaintext) >>> def my_dec( ... key: bytes, ... ciphertext: bytes, ... nonce: bytes, ... *, ... init_counter: int = 0 ... ) -> bytes: ... cipher = pyChaCha20.new(key=key, nonce=nonce) ... if init_counter > 0: ... cipher.seek(64 * init_counter) ... return cipher.decrypt(ciphertext) - And we test the functions we defined. - >>> mode = ChaCha20.Mode.CHACHA20 >>> results_dict = ChaCha20.test(my_enc, my_dec, mode) [Wycheproof] ... >>> assert results_dict.check() 
Test the output of an implementation¶
Note
From the CLI you can test the file with the test output ChaCha20 command.
- crypto_condor.primitives.ChaCha20.verify_file(filename, mode, operation)¶
- Tests the output of an implementation. - Tests an implementation from a set of inputs passed to it and the outputs it returned. These inputs are passed to the internal implementation and the results are compared to the outputs given. - Format:
- One line per operation. 
- Lines are separated by newlines ( - \n).
- Lines that start with # are counted as comments and ignored. 
- Arguments written in hexadecimal and separated by slashes. 
- Arguments in brackets are optional. If omitted, don’t include the trailing slash. 
- For ChaCha20, the order of the arguments is: 
 - key/input/output/nonce[/init_counter] - For ChaCha20-Poly1305, the order of the arguments is: 
 - key/input/output/nonce/mac[/aad] - Where:
- inputis the plaintext when encrypting (resp. the ciphertext when decrypting).
- outputis the ciphertext when encrypting (resp. the plaintext when decrypting).
- nonceis the nonce used for that operation.
- init_counteris the initial position in the keystream to seek before the operation.
- macis the MAC tag. When encrypting, it is compared to the MAC returned by the internal implementation. When decrypting it is used to authenticate the ciphertext.
- aadis the associated data. Can be empty.
 
 
 
 - Parameters:
- Returns:
- The results of running the inputs of each line with the internal implementation, and comparing both outputs to see if they match. - Parsing errors are considered as test failures. 
- Return type:
 - Example - Let’s generate 10 random tuples of (key, plaintext, nonce), encrypt the plaintexts using PyCryptodome, and write everything to a file. - >>> import random >>> from crypto_condor.primitives import ChaCha20 >>> from Crypto.Cipher import ChaCha20 as pyChaCha20 >>> filename = "/tmp/crypto-condor-test/chacha20-verify.txt" >>> with open(filename, "w") as file: ... for _ in range(10): ... # Pick random values ... key = random.randbytes(32) ... plaintext = random.randbytes(64) ... nonce = random.randbytes(12) ... # Encrypt ... cipher = pyChaCha20.new(key=key, nonce=nonce) ... ciphertext = cipher.encrypt(plaintext) ... # Convert to hexadecimal ... kh, nh = key.hex(), nonce.hex() ... ph, ch = plaintext.hex(), ciphertext.hex() ... # Create the line to write, note the absent init_counter ... line = f"{kh}/{ph}/{ch}/{nh}\n" ... _ = file.write(line) - Now we can test the file. - >>> mode = ChaCha20.Mode.CHACHA20 >>> operation = ChaCha20.Operation.ENCRYPT >>> results = ChaCha20.verify_file(filename, mode, operation) Testing ... >>> assert results.check() 
Run a wrapper¶
Note
Available wrappers are defined by the Wrapper enum.
- crypto_condor.primitives.ChaCha20.run_wrapper(language, mode, *, resilience=True, encrypt=True, decrypt=True)¶
- Runs a wrapper. - Parameters:
- Keyword Arguments:
- resilience – Whether to run resilience test vectors. 
- encrypt – Whether to test the encryption. 
- decrypt – Whether to test the decryption. 
 
- Returns:
- The results from - test().
- Return type:
 
Protocols¶
- protocol crypto_condor.primitives.ChaCha20.Encrypt¶
- Represents a function that encrypts with ChaCha20. - Encryption functions must behave like one of the - __call__()overloads below to be tested with this module. The first corresponds to ChaCha20, the second to ChaCha20-Poly1305.- Classes that implement this protocol must have the following methods / attributes: - __call__(
- key: bytes,
- plaintext: bytes,
- nonce: bytes,
- *,
- init_counter: int = 0,
- __call__(
- key: bytes,
- plaintext: bytes,
- nonce: bytes,
- *,
- aad: bytes | None,
- Encrypts with ChaCha20(-Poly1305). - Parameters:
- key – The symmetric key. 
- plaintext – The message to encrypt. 
- nonce – The nonce to use for this message. 
 
- Keyword Arguments:
- init_counter – (ChaCha20 only) A position to seek in the keystream before encrypting, in bytes. 
- aad – (ChaCha20-Poly1305 only) The associated data, can be empty or None. 
 
- Returns:
- (ChaCha20) The ciphertext. - (ChaCha20-Poly1305) A (ciphertext, MAC) tuple. 
 
 
- protocol crypto_condor.primitives.ChaCha20.Decrypt¶
- Represents a function that decrypts with ChaCha20. - Decryption functions must behave like one of the - __call__()overloads below to be tested with this module. The first corresponds to ChaCha20, the second to ChaCha20-Poly1305.- Classes that implement this protocol must have the following methods / attributes: - __call__(
- key: bytes,
- ciphertext: bytes,
- nonce: bytes,
- *,
- init_counter: int = 0,
- __call__(
- key: bytes,
- ciphertext: bytes,
- nonce: bytes,
- *,
- mac: bytes,
- aad: bytes | None,
- Decrypts with ChaCha20(-Poly1305). - Parameters:
- key – The symmetric key. 
- ciphertext – The message to decrypt. 
- nonce – The nonce to use for this message. 
 
- Keyword Arguments:
- init_counter – (ChaCha20 only) A position to seek in the keystream before encrypting, in bytes. 
- mac – (ChaCha20-Poly1305 only) The MAC tag to use for authenticating the ciphertext. 
- aad – (ChaCha20-Poly1305 only) The associated data, can be empty or None. 
 
- Returns:
- (ChaCha20) The plaintext. - (ChaCha20-Poly1305) If the MAC is valid, a (plaintext, True) tuple. Otherwise the plaintext should not be released, so return a (None, False) tuple.