AES¶
Module to test AES implementations.
The crypto_condor.primitives.AES
module can test implementations of AES encryption and decryption using several modes of operations with the
test_encrypt()
and test_decrypt()
functions. Supported modes are defined by
the Mode
enum.
Test encryption¶
- crypto_condor.primitives.AES.test_encrypt(encrypt, mode, keylen, *, compliance=True, resilience=False)¶
Tests a function that encrypts with AES.
- Parameters:
- Keyword Arguments:
compliance – Whether to use compliance test vectors.
resilience – Whether to use resilience test vectors.
- Returns:
A dictionary of results.
- Return type:
Example
Let’s test PyCryptodome with AES-256-GCM.
We start by importing the AES module.
>>> from crypto_condor.primitives import AES
We need to wrap the encryption to match the signature of
Encrypt
.>>> from Crypto.Cipher import AES as pycAES
>>> def aes_gcm( ... key: bytes, ... plaintext: bytes, ... *, ... iv: bytes | None = None, ... aad: bytes | None = None, ... mac_len: int = 0, ... ) -> AES.CiphertextAndTag: ... cipher = pycAES.new(key, pycAES.MODE_GCM, nonce=iv, mac_len=mac_len) ... if aad is not None: ... cipher.update(aad) ... return cipher.encrypt_and_digest(plaintext)
We define the parameters to test using the corresponding enums. We can use them directly but this simplifies the function call.
>>> mode, keylen = AES.Mode.GCM, AES.KeyLength.AES256
And now, we test the function.
>>> res = AES.test_encrypt(aes_gcm, mode, keylen) [GCM][256][NIST CAVP] Testing encryption ... >>> assert res.check()
Test decryption¶
- crypto_condor.primitives.AES.test_decrypt(decrypt, mode, keylen, *, compliance=True, resilience=False)¶
Tests a function that decrypt with AES.
- Parameters:
- Keyword Arguments:
compliance – Whether to use compliance test vectors.
resilience – Whether to use resilience test vectors.
- Returns:
A dictionary of results.
- Return type:
Example
Let’s test PyCryptodome with AES-256-GCM.
We start by importing the AES module.
>>> from crypto_condor.primitives import AES
We need to wrap the encryption to match the signature of
Decrypt
.>>> from Crypto.Cipher import AES as pycAES
>>> def aes_gcm( ... key: bytes, ... ciphertext: bytes, ... *, ... iv: bytes | None = None, ... aad: bytes | None = None, ... mac: bytes | None = None, ... mac_len: int = 0, ... ) -> AES.CiphertextAndTag: ... cipher = pycAES.new(key, pycAES.MODE_GCM, nonce=iv, mac_len=mac_len) ... if aad is not None: ... cipher.update(aad) ... try: ... pt = cipher.decrypt_and_verify(ciphertext, mac) ... return (pt, True) ... except ValueError: ... return (None, False)
We define the parameters to test using the corresponding enums. We can use them directly but this simplifies the function call.
>>> mode, keylen = AES.Mode.GCM, AES.KeyLength.AES256
And now, we test the function.
>>> res = AES.test_decrypt(aes_gcm, mode, keylen) [GCM][256][NIST CAVP] Testing decryption ... >>> assert res.check()
Test the output of encryption¶
- crypto_condor.primitives.AES.test_output_encrypt(filename, mode)¶
Tests the output of an implementation of AES encryption.
Attention
This function uses the internal implementation of AES, which must be compiled and installed locally. This is done automatically when the function is called for the first time. If the installation fails, this function will not work.
- Format:
One set of arguments per line.
Lines are separated by newlines
\n
.Lines that start with
#
are counted as comments and ignored.Arguments are written in hexadecimal and separated by forward slashes.
For ECB, the order is:
key/plaintext/ciphertext
For other classic modes of operation (CBC, CTR, CFB) the order is:
key/plaintext/ciphertext/iv
For AEAD modes (CCM, GCM) the order is:
key/plaintext/ciphertext/iv/[aad]/[mac]
- Where:
key
is the key used.plaintext
is the input message.ciphertext
is the result of the operation.iv
is the IV or nonce used for that operation.aad
is the associated data. It is optional and can be empty. Even if not used, the corresponding slashes must be present.mac
is the MAC tag generated when encrypting.
- Parameters:
filename (str) – The name of the file to test.
mode (Mode) – The mode of operation used.
- Returns:
A dictionary of Results, containing a single instance.
- Return type:
Test the output of decryption¶
- crypto_condor.primitives.AES.test_output_decrypt(filename, mode)¶
Tests the output of an implementation of AES decryption.
Attention
This function uses the internal implementation of AES, which must be compiled and installed locally. This is done automatically when the function is called for the first time. If the installation fails, this function will not work.
- Format:
One set of arguments per line.
Lines are separated by newlines
\n
.Lines that start with
#
are counted as comments and ignored.Arguments are written in hexadecimal and separated by forward slashes.
For ECB, the order is:
key/ciphertext/plaintext
For other classic modes of operation (CBC, CTR, CFB) the order is:
key/ciphertext/plaintext/iv
For AEAD modes (CCM, GCM) the order is:
key/ciphertext/plaintext/iv/[aad]/[mac]
- Where:
key
is the key used.ciphertext
is the input message.plaintext
is the result of the operation.iv
is the IV or nonce used for that operation.aad
is the associated data. It is optional and can be empty. Even if not used, the corresponding slashes must be present.mac
is the MAC tag generated when encrypting.
- Parameters:
filename (str) – The name of the file to test.
mode (Mode) – The mode of operation used.
- Returns:
A dictionary of Results, containing a single instance.
- Return type:
Parameters¶
- enum crypto_condor.primitives.AES.Mode(value)¶
Supported AES modes of operation.
- Member Type:
str
Valid values are as follows:
- ECB = <Mode.ECB: 'ECB'>¶
- CBC = <Mode.CBC: 'CBC'>¶
- CBC_PKCS7 = <Mode.CBC_PKCS7: 'CBC-PKCS7'>¶
- CFB = <Mode.CFB: 'CFB'>¶
- CFB8 = <Mode.CFB8: 'CFB8'>¶
- CFB128 = <Mode.CFB128: 'CFB128'>¶
- CTR = <Mode.CTR: 'CTR'>¶
- GCM = <Mode.GCM: 'GCM'>¶
- CCM = <Mode.CCM: 'CCM'>¶
The
Enum
and its members also have the following methods:- classmethod classic_modes()¶
Returns a list of all supported classic (non AEAD) modes.
crypto-condor
supports ECB, CBC, CBC with PKCS#7 padding, CFB8, CFB128, and CTR.
- enum crypto_condor.primitives.AES.KeyLength(value)¶
Supported key lengths.
AES has three different key lengths: 128, 192, and 256 bits. Since users may want to test a specific key length, this enum defines these three options alongside the
KeyLength.ALL
option to test all three.- Member Type:
int
Valid values are as follows:
- ALL = <KeyLength.ALL: 0>¶
- AES128 = <KeyLength.AES128: 128>¶
- AES192 = <KeyLength.AES192: 192>¶
- AES256 = <KeyLength.AES256: 256>¶
Protocols¶
- protocol crypto_condor.primitives.AES.Encrypt¶
Represents a function that encrypts with AES.
Encryption functions must behave like one of the
__call__
functions to be tested with this module. Each correspond to one or more modes of operation. In order:ECB
CBC or CTR or CFB8 or CFB128
CCM or GCM
Classes that implement this protocol must have the following methods / attributes:
- __call__(key: bytes, plaintext: bytes) bytes ¶
- __call__(key: bytes, plaintext: bytes, *, iv: bytes) bytes
- __call__(
- key: bytes,
- plaintext: bytes,
- *,
- iv: bytes | None,
- aad: bytes | None,
- mac_len: int = 0,
Encrypts with AES.
- Parameters:
key – The symmetric key.
plaintext – The input to encrypt.
- Keyword Arguments:
iv – (All modes except ECB) The IV or nonce.
aad – (CCM/GCM) The associated data.
mac_len – (CCM/GCM) The length of the authentication tag.
- Returns:
(ECB/CBC/CTR/CFB) The resulting ciphertext.
(CCM/GCM) A (ciphertext, tag) tuple.
- protocol crypto_condor.primitives.AES.Decrypt¶
Represents a function that decrypts with AES.
Decryption functions must behave like one of the
__call__
functions to be tested with this module. Each correspond to one or more modes of operation. In order:ECB
CBC or CTR or CFB8 or CFB128
CCM or GCM
Classes that implement this protocol must have the following methods / attributes:
- __call__(key: bytes, ciphertext: bytes) bytes ¶
- __call__(key: bytes, ciphertext: bytes, *, iv: bytes | None) bytes
- __call__(
- key: bytes,
- ciphertext: bytes,
- *,
- iv: bytes | None,
- aad: bytes | None,
- mac: bytes | None,
- mac_len: int = 0,
Decrypts with AES.
- Parameters:
key – The symmetric key.
ciphertext – The input to decrypt.
- Keyword Arguments:
iv – (All modes except ECB) The IV or nonce.
aad – (CCM/GCM) The associated data.
mac – (CCM/GCM) The authentication tag.
mac_len – (CCM/GCM) The length of the authentication tag in bytes.
- Returns:
(ECB/CBC/CTR/CFB) The resulting plaintext.
(CCM/GCM) If the MAC is valid it returns (plaintext, True). Otherwise the plaintext should not be release so it returns (None, False).
Notes
We decided to return None when the MAC verification fails to differentiate from the case where the message is empty, which is a valid case, and is tested by some test vectors. It serves as a clear sign that even in case we don’t test the verification status “this is not the plaintext you’re looking for”.
Run a wrapper¶
- crypto_condor.primitives.AES.run_python_wrapper(wrapper, compliance, resilience)¶
Runs an AES Python wrapper.
See AES wrapper for a description of the wrappers.
- Parameters:
wrapper (Path) – A path to the wrapper to run. Must be a Python program.
compliance (bool) – Whether to use compliance test vectors.
resilience (bool) – Whether to use resilience test vectors.
- Returns:
A dictionary of results.
- Return type: