Introducing python-aead

- (3 min read)

Cryptography libraries often have complicated APIs with many different options to tweak. It is a goal PyCA's cryptography library to provide safe and easy to use APIs for common cryptographic tasks. To that end, the cryptography package has a Fernet recipe for symmetric encryption derived from the original Ruby implementation and specification. However, the Fernet recipe lacks the ability to authentiate (without encrypting) arbitrary data.

To make up for that use case not being covered by Fernet, I have written and released on PyPI a library called aead. It can be installed with pip.

$ pip install aead

The aead library is based on a IETF Internet Draft from David McGrew. It is essentially AES_128_CBC and HMAC_SHA_256 composed with an encrypt-then-mac construction. It relies on the cryptography library for the cryptographic primitives.

It has a simple to use API heavily inspired by the Fernet recipe in the cryptography library.

The module contains a single class that can be imported.

from aead import AEAD

The class takes requires an encryption key to be initialized. The key has to be 32 bytes long and encoded with base64url as specified in [[RFC4648]]. The library provides a classmethod to generate a suitable random key.

cryptor = AEAD(AEAD.generate_key())

After initializing the object, encryption can be done by calling the .encrypt() method. The .encrypt() method takes two paremeters, the first being the data you want to encrypt and the second being associated data that you want to authenticate but not encrypt. The second parameter is optional and can be left out if there isn't any data to authenticate.

ct = cryptor.encrypt(b"Hello, World!", b"Additional Data")

.encrypt() returns base64url encoded cipher text.

Decrypting any data encrypted with aead is similar. Simply call .decrypt() in place of .encrypt(). The .decrypt() method takes two parameters, the first being the cipher text that needs decrypting and the second being the associated data that was authenticated.

If the cipher text is corrupted or the associated data provided during the decryption process does not match the associated data provided during encryption, a ValueError is raised, otherwise the decrypted plain text is returned.

The repository for aead can be found on GitHub and the file in the repository should be treated as the source of truth if any information there differs from this blog post due to changes over time.