Modern modes of operation for symmetric block ciphers¶
Classic modes of operation such as CBC only provide guarantees over the confidentiality of the message but not over its integrity. In other words, they don’t allow the receiver to establish if the ciphertext was modified in transit or if it really originates from a certain source.
For that reason, classic modes of operation have been often paired with
a MAC primitive (such as Crypto.Hash.HMAC
), but the
combination is not always straightforward, efficient or secure.
Recently, new modes of operations (AEAD, for Authenticated Encryption with Associated Data) have been designed to combine encryption and authentication into a single, efficient primitive. Optionally, some part of the message can also be left in the clear (non-confidential associated data, such as headers), while the whole message remains fully authenticated.
In addition to the ciphertext and a nonce / IV, AEAD modes require the additional delivery of a MAC tag.
The API of an AEAD cipher object is richer, as it include methods normally found in a MAC object:
- The
update()
method consumes data (if any) which must be authenticated but not encrypted. Note that any data passed toencrypt()
ordecrypt()
is automatically authenticated. - The
digest()
method creates an authentication tag (MAC tag) at the end of the encryption process (the varianthexdigest()
exists to output the tag as a hexadecimal string). - The
verify()
method checks if the provided authentication tag (MAC tag) is valid at the end of the decryption process (the varianthexverify()
exists in case the MAC tag is a hexadecimal string). - The
encrypt_and_digest()
method encrypts and creates a MAC tag in one go. - The
decrypt_and_verify()
method decrypts and checks a MAC tag in one go.
The state machine for a cipher object becomes:
CCM mode¶
Constant: Crypto.Cipher.<cipher>.MODE_CCM
.
Counter with CBC-MAC, defined in RFC3610 or NIST SP 800-38C. It only works with ciphers having block size 128 bits (like AES).
The new()
function expects the following extra parameters:
nonce
(byte string): a non-repeatable value, of length between 7 and 13 bytes. The longer the nonce, the smaller the allowed message size (with a nonce of 13 bytes, the message cannot exceed 64KBi). If not present, a random 11 bytes long nonce will be created (the maximum message size is 8GBi).mac_len
(integer): the desired length of the MAC tag (default if not present: 16 bytes).msg_len
(integer): pre-declaration of the length of the message to encipher. If not specified,encrypt()
anddecrypt()
can only be called once.assoc_len
(integer): pre-declaration of the length of the associated data. If not specified, some extra buffering will take place internally.
The cipher object has a read-only attribute nonce
.
EAX mode¶
Constant: Crypto.Cipher.<cipher>.MODE_EAX
.
An AEAD mode designed for NIST by Bellare, Rogaway, and Wagner in 2003.
The new()
function expects the following extra parameters:
nonce
(byte string): a non-repeatable value, of arbitrary length. If not present, a random nonce of the recommended length (16 bytes) will be created.mac_len
(integer): the desired length of the MAC tag (default if not present: 16 bytes).
The cipher object has a read-only attribute nonce
.
GCM mode¶
Constant: Crypto.Cipher.<cipher>.MODE_GCM
.
Galois/Counter Mode, defined in NIST SP 800-38D. It only works in combination with a 128 bits cipher like AES.
The new()
function expects the following extra parameters:
nonce
(byte string): a non-repeatable value, of arbitrary length. If not present, a random nonce of the recommended length (16 bytes) will be created.mac_len
(integer): the desired length of the MAC tag (default if not present: 16 bytes).
The cipher object has a read-only attribute nonce
.
SIV mode¶
Constant: Crypto.Cipher.<cipher>.MODE_SIV
.
Synthetic Initialization Vector (SIV), defined in RFC5297. It only works with ciphers with a block size of 128 bits (like AES).
Although less efficient than other modes, SIV is nonce misuse-resistant: accidental reuse of the nonce does not jeopardize the security as it happens with CCM or GCM. As a matter of fact, operating without a nonce is not an error per se: the cipher simply becomes deterministic. In other words, a message gets always encrypted into the same ciphertext.
Example of deterministic encryption with SIV:
>>> from Crypto.Cipher import AES
>>> from Crypto.Random import get_random_bytes
>>> key = get_random_bytes(32)
>>> header = b'Non sensitive information'
>>> plaintext = b'Secret message'
>>>
>>> cipher = AES.new(key, AES.MODE_SIV)
>>> cipher.update(header)
>>> ciphertext, tag = cipher.encrypt_and_digest(plaintext)
Example of deterministic decryption with SIV:
>>> from Crypto.Cipher import AES
>>> # ... acquire key and receive header, ciphertext and tag
>>>
>>> cipher = AES.new(key, AES.MODE_SIV)
>>> cipher.update(header)
>>> try:
>>> plaintext = cipher.decrypt_and_verify(ciphertext, tag)
>>> except ValueError:
>>> print("Invalid message")
One side-effect is that encryption (or decryption) must take place in one go
with the method encrypt_and_digest()
(or decrypt_and_verify()
).
You cannot use encrypt()
or decrypt()
. The state diagram is therefore:
The new()
function accepts one optional parameter, in addition to key and mode:
nonce
(bytes, bytearray, memoryview): a non-repeatable value, of arbitrary length. If not present, the encryption becomes deterministic.
The length of the key passed to new()
must be twice
as required by the underlying block cipher (e.g. 32 bytes for AES-128).
Each call to the method update()
consumes an full piece of associated data.
That is, the sequence:
>>> siv_cipher.update(b"builtin")
>>> siv_cipher.update(b"securely")
is not equivalent to:
>>> siv_cipher.update(b"built")
>>> siv_cipher.update(b"insecurely")
The cipher object has a read-only attribute nonce
.
OCB mode¶
Constant: Crypto.Cipher.<cipher>.MODE_OCB
.
Offset CodeBook mode, a cipher designed by Rogaway and specified in RFC7253 (more specifically, this module implements the last variant, OCB3). It only works in combination with a 128 bits cipher like AES.
OCB is patented in USA but free licenses exist for software implementations meant for non-military purposes and open source.
The new()
function expects the following extra parameters:
nonce
(byte string): a non-repeatable value, of length between 1 and 15 bytes.. If not present, a random nonce of the recommended length (15 bytes) will be created.mac_len
(integer): the desired length of the MAC tag (default if not present: 16 bytes).
The cipher object has a read-only attribute nonce
.