Struct AES128
pub struct AES128 {}
Trait implementations
impl MessageEncryption for AES128
pub fn encrypt<let PlaintextLen: u32>(
plaintext: [Field; PlaintextLen],
recipient: AztecAddress,
) -> [Field; 15]
pub unconstrained fn decrypt(
ciphertext: BoundedVec<Field, 15>,
recipient: AztecAddress,
) -> Option<BoundedVec<Field, 12>>
AES128-CBC encryption for Aztec protocol messages.
Overview
The plaintext is an array of up to
MESSAGE_PLAINTEXT_LEN(12) fields. The output is always exactlyMESSAGE_CIPHERTEXT_LEN(15) fields, regardless of plaintext size. Unused trailing fields are filled with random data so that all encrypted messages are indistinguishable by size.PKCS#7 Padding
AES operates on 16-byte blocks, so the plaintext must be padded to a multiple of 16. PKCS#7 padding always adds at least 1 byte (so the receiver can always detect and strip it), which means:
In general: if the plaintext is already a multiple of 16, a full 16-byte padding block is appended.
Encryption Steps
1. Body encryption. The plaintext fields are serialized to bytes (32 bytes per field) and AES-128-CBC encrypted. Since 32 is a multiple of 16, PKCS#7 always adds a full 16-byte padding block (see above):
2. Header encryption. The byte length of
body_ctis stored as a 2-byte big-endian integer. This 2-byte header plaintext is then AES-encrypted; PKCS#7 pads the remaining 14 bytes to fill one 16-byte AES block, producing a 16-byte header ciphertext:Wire Format
Messages are transmitted as fields, not bytes. A field is ~254 bits and can safely store 31 whole bytes, so we need to pack our byte data into 31-byte chunks. This packing drives the wire format.
Step 1 -- Assemble bytes. The ciphertexts are laid out in a byte array, padded with random bytes to a multiple of 31 so it divides evenly into fields:
Step 2 -- Pack into fields. The byte array is split into 31-byte chunks, each stored in one field. The ephemeral public key x-coordinate is prepended as its own field. Any remaining fields (up to 15 total) are filled with random data so that all messages are the same size:
Key Derivation
Two (key, IV) pairs are derived from the ECDH shared secret via Poseidon2 hashing with different domain separators: one pair for the body ciphertext and one for the header ciphertext.