Crate zears

Source
Expand description

AEZ [sic!] v5 encryption implemented in Rust.

§☣️ Cryptographic hazmat ☣️

This crate is not battle tested, nor is it audited. Its usage for critical systems is strongly discouraged. It mainly exists as a learning exercise.

§AEZ encryption

AEZ is an authenticated encryption scheme. It works in two steps:

  • First, a known authentication block (a fixed number of zeroes) is appended to the message.
  • Second, the message is enciphered with an arbitrary-length blockcipher.

The blockcipher is tweaked with the key, the nonce and additional data.

The paper explains the security concepts of AEZ in more detail.

§AEZ encryption (for laypeople)

The security property of encryption schemes says that an adversary without key must not learn the content of a message. However, the adversary might still be able to modify the message. For example, in AES-CTR (or other stream ciphers), flipping a bit in the ciphertext means that the same bit will be flipped in the plaintext once the message is decrypted. This allows for “planned” changes.

Authenticated encryption solves this problem by including a mechanism to detect changes. This can be done for example by including a MAC, or using a mode like GCM (Galois counter mode). In many cases, not only the integrity of the ciphertext can be verified, but the user can provide additional data during encryption and decryption which will also have its integrity be verified. This is called an authenticated encryption with associated data scheme, AEAD for short.

AEZ employs a nifty technique in order to realize an AEAD scheme: The core of AEZ is an enciphering scheme, which in addition to “hiding” its input is also very “unpredictable” when bits are flipped. Similar to a hash function, if the ciphertext is changed slightly (by flipping a bit), the resulting plaintext will be unpredictably and completely different.

With this property, authenticated encryption can be realized implicitly: The message is padded with a known string before enciphering it. If, after deciphering, this known string is not present, the message has been tampered with. Since the enciphering is parametrized by the key, a nonce and arbitrary additional data, we can verify the integrity of associated data as well.

§Other implementations

As this library is a learning exercise, if you want to use AEZ in practice, it is suggested to use the aez crate which provides bindings to the C reference implementation of AEZ.

zears differs from aez in that …

  • it works on platforms without hardware AES support, using the “soft” backend of aes.
  • it does not inherit the limitations of the reference implementation in regards to nonce length, authentication tag length, or the maximum of one associated data item.

zears is tested with test vectors generated from the reference implementation using Nick Mathewson’s tool.

§Example usage

The core of this crate is the Aez struct, which provides the high-level API. There is usually not a lot more that you need:

let aez = Aez::new(b"my secret key!");
let cipher = aez.encrypt(b"nonce", &[b"associated data"], 16, b"message");
let plaintext = aez.decrypt(b"nonce", &[b"associated data"], 16, &cipher);
assert_eq!(plaintext.unwrap(), b"message");

// Flipping a bit leads to decryption failure
let mut cipher = aez.encrypt(b"nonce", &[], 16, b"message");
cipher[0] ^= 0x02;
let plaintext = aez.decrypt(b"nonce", &[], 16, &cipher);
assert!(plaintext.is_none());

// Similarly, modifying the associated data leads to failure
let cipher = aez.encrypt(b"nonce", &[b"foo"], 16, b"message");
let plaintext = aez.decrypt(b"nonce", &[b"bar"], 16, &cipher);
assert!(plaintext.is_none());

§Feature flags & compilation hints

  • Enable feature simd (requires nightly due to the portable_simd Rust feature) to speed up encryption and decryption by using SIMD instructions (if available).
  • Use target-cpu=native (e.g. by setting RUSTFLAGS=-Ctarget-cpu=native) to make the compiler emit vectorized AES instructions (if available). This can speed up encryption/decryption at the cost of producing less portable code.

On my machine, this produces the following results (for the encrypt_inplace/2048 benchmark):

Compilation setupThroughputSpeedup
baseline488.78 MiB/s
+simd967.91 MiB/s+98.187%
target-cpu=native2.0062 GiB/s+314.67%
+simd, target-cpu=native3.3272 GiB/s+592.01%
aez crate4.8996 GiB/s

Structs§

Aez
AEZ encryption scheme.