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 theportable_simd
Rust feature) to speed up encryption and decryption by using SIMD instructions (if available). - Use
target-cpu=native
(e.g. by settingRUSTFLAGS=-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 setup | Throughput | Speedup |
---|---|---|
baseline | 488.78 MiB/s | |
+simd | 967.91 MiB/s | +98.187% |
target-cpu=native | 2.0062 GiB/s | +314.67% |
+simd, target-cpu=native | 3.3272 GiB/s | +592.01% |
aez crate | 4.8996 GiB/s |
Structs§
- Aez
- AEZ encryption scheme.