AEAD (Authenticated Encryption with Associated Data) implementation using Poseidon2 hash.<br /><br />This implementation uses the `crypto_stream` instruction for optimal performance.<br />The scheme follows the MonkeySpongeWrap construction:<br />1. Initialize Poseidon2 sponge state with key and nonce<br />2. Absorb associated data padding (currently [1,0,0,0,0,0,0,0])<br />3. Process plaintext blocks using `crypto_stream` + `hperm`<br />4. Generate authentication tag from final sponge state<br /><br />Note: Associated data (AD) is currently NOT supported. Only empty AD is handled,<br />which is represented by the padding block [1,0,0,0,0,0,0,0].<br />
## miden::core::crypto::aead
| Procedure | Description |
| ----------- | ------------- |
| encrypt | Encrypts plaintext data from memory using the `crypto_stream` instruction.<br /><br />This procedure encrypts plaintext and automatically adds a padding block at the end.<br />The padding block [1, 0, 0, 0, 0, 0, 0, 0] is written to memory and encrypted, ensuring<br />proper AEAD operation without requiring the caller to handle padding manually.<br />This, however, requires the plaintext length to be a multiple of 8. This assumption is made<br />both in this procedure as well as in the decryption procedure.<br /><br />Input: [key(4), nonce(4), src_ptr, dst_ptr, num_blocks, ...]<br />Output: [tag(4), ...]<br /><br />Where:<br />- key is the encryption key (4 elements)<br />- nonce is the initialization vector (4 elements)<br />- src_ptr points to plaintext in memory (must be word-aligned)<br />- dst_ptr points to where ciphertext will be written (must be word-aligned)<br />- num_blocks is the number of 8-element plaintext data blocks (NO padding included)<br />- tag is the authentication tag returned on stack (4 elements)<br /><br />Memory Layout:<br />- Input at src_ptr: [plaintext_block_0(8), ..., plaintext_block_n(8)]<br />Length: num_blocks * 8 elements (must be multiple of 8)<br /><br />- Output at dst_ptr: [ciphertext_block_0(8), ..., ciphertext_block_n(8), encrypted_padding(8)]<br />Length: (num_blocks + 1) * 8 elements<br />The padding block is automatically added and encrypted<br /><br />- Standard format: the tag is stored right after ciphertext to create:<br />[ciphertext_blocks(num_blocks * 8), encrypted_padding(8), tag(4)]<br />Tag location: dst_ptr + (num_blocks + 1) * 8<br /><br />Memory Requirements:<br />- Plaintext must be at word-aligned addresses (addr % 4 == 0)<br />- Each block is 8 field elements (2 words)<br />- Blocks must be stored contiguously in memory<br />- src_ptr and dst_ptr MUST be different (in-place encryption not supported)<br />This is because crypto_stream reads and writes in the same clock cycle<br /><br />Padding:<br />- Padding is AUTOMATIC - caller should NOT pad the plaintext<br />- The procedure writes [1, 0, 0, 0, 0, 0, 0, 0] to dst_ptr + (num_blocks * 8)<br />- This padding block is then encrypted along with the data<br />- For empty plaintext (num_blocks = 0), only the padding block is encrypted<br /><br />Cycles (estimate): 77 + 2 * n<br />Where:<br />- n = number of field elements encrypted (includes the final padding block)<br />- For num_blocks data blocks: n = 8 * (num_blocks + 1)<br /> |
| decrypt | Decrypts and authenticates ciphertext using non-deterministic advice.<br /><br />This procedure implements AEAD decryption with automatic tag verification and<br />automatic padding handling. It mirrors the encrypt procedure's padding behavior.<br /><br />Decryption Flow:<br />1. Computes tag location: src_ptr + (num_blocks + 1) * 8<br />2. Emits event for host to decrypt ciphertext (data blocks + padding block)<br />3. Loads plaintext data blocks from advice into dst_ptr (num_blocks * 8 elements)<br />4. Calls encrypt which reads data blocks and adds padding automatically<br />5. Re-encrypts data + padding to compute authentication tag<br />6. Compares computed tag with tag from memory at src_ptr + (num_blocks + 1) * 8<br />7. Halts execution with assertion failure if tags don't match<br /><br />Input: [key(4), nonce(4), src_ptr, dst_ptr, num_blocks, ...]<br />Output: [] (empty stack on success, halts on failure)<br /><br />Where:<br />- key is the decryption key (4 elements)<br />- nonce is the initialization vector (4 elements)<br />- src_ptr points to ciphertext + encrypted_padding + tag in memory (word-aligned)<br />- dst_ptr points to where plaintext will be written (word-aligned)<br />- num_blocks is the number of 8-element plaintext data blocks (NO padding)<br /><br />Memory Layout:<br />- Input at src_ptr: [ciphertext_blocks(num_blocks * 8), encrypted_padding(8), tag(4)]<br />The encrypted padding is at: src_ptr + (num_blocks * 8)<br />The tag is at: src_ptr + (num_blocks + 1) * 8<br /><br />- Output at dst_ptr: [plaintext_block_0(8), ..., plaintext_block_n(8), padding(8)]<br />Length: (num_blocks + 1) * 8 elements<br />The padding block [1, 0, 0, 0, 0, 0, 0, 0] is automatically written<br />Caller can ignore or remove the padding block if needed<br /><br />Event: Emits AEAD_DECRYPT event with (nonce, key, src_ptr, dst_ptr, num_blocks)<br />The host event handler must:<br />- Read full ciphertext from memory at src_ptr ((num_blocks + 1) * 8 elements)<br />- Read authentication tag from memory at src_ptr + (num_blocks + 1) * 8<br />- Decrypt and verify tag using reference implementation<br />- Extract only data blocks (first num_blocks * 8 elements) from decrypted plaintext<br />- Insert data blocks (WITHOUT padding) into advice map (keyed by nonce)<br /><br />Memory Requirements:<br />- Same as encrypt: word-aligned addresses, contiguous blocks<br />- src_ptr and dst_ptr MUST be different (in-place operation not supported)<br /><br />Security:<br />- Tag verification happens in the MASM procedure via re-encryption<br />- Execution halts with assertion failure if tag verification fails<br />- If execution completes successfully, the plaintext at dst_ptr is authenticated<br /><br />Non-Determinism Soundness:<br />This procedure uses non-deterministic advice to obtain the plaintext, which is sound<br />because:<br />1. The prover provides claimed plaintext via advice (untrusted input)<br />2. This procedure re-encrypts the claimed plaintext with the same (key, nonce)<br />3. Due to deterministic encryption, the same plaintext produces the same ciphertext<br />4. The computed tag cryptographically commits to both plaintext and ciphertext<br />5. Comparing tags verifies that the claimed plaintext is the unique plaintext that<br />encrypts to the given ciphertext under the given (key, nonce)<br /><br />This approach is secure because:<br />- The MASM procedure verifies the tag when calling the encryption procedure<br />- The tag acts as a cryptographic commitment<br />- The deterministic keystream creates a bijection between plaintext and ciphertext<br />- Any deviation from correct plaintext causes assertion failure<br /><br />Note: This procedure does NOT remove padding. The caller must handle padding removal.<br /><br />Cycles (estimate): 177 + 3.5 * n<br />Where:<br />- n = number of field elements in the plaintext (excludes the padding block)<br />- For num_blocks data blocks: n = 8 * num_blocks<br /> |