Skip to main content

Module cipher

Module cipher 

Source
Expand description

The confidentiality and integrity boundary for journaled payloads.

Journal payloads (step results, promise resolutions, checkpoint snapshots) are written to a database file that — for shared-DB and Restate deployments — sits outside the process trust boundary. This module defines the contract that protects them:

  • PayloadCipher — the AEAD seal/open trait. The concrete XChaCha20-Poly1305 implementation lives in a consuming crate (the binary or a zeph-core-side module), keyed from the vault, so zeph-durable stays a pure Layer-0 abstraction with no cryptographic dependency (INV-1). The backend receives the cipher as Option<Arc<dyn PayloadCipher>> at construction.
  • PayloadAad — the associated data bound into every seal. Binding (execution_id, step_id, entry_kind, idem_key) makes a sealed blob un-relocatable: a result sealed for one step cannot be opened as the result of another step or another execution (fail-closed → CipherError::AuthenticationDurableError::ReplayIntegrity).
  • EntryKindTag — a Copy discriminator for the entry shape, used inside the AAD so the cipher never needs to see the payload-bearing crate::EntryKind itself.
  • CipherError — seal/open failures, reported as metadata only (INV-5): no payload bytes, nonces, or key material ever appear in an error.
  • ensure_payload_within_limit — the read-side size guard (INV-11) that fails closed before any decryption or decode is attempted.

§Stored blob layout

A concrete cipher MUST produce key_id(1) || nonce(24) || ciphertext || tag(16). The leading key-id byte selects the key during a rotation window; the 24-byte nonce is the XChaCha20 extended nonce, freshly drawn from a CSPRNG on every seal (INV-7).

§Examples

use zeph_durable::{ExecutionId, StepId};
use zeph_durable::cipher::{EntryKindTag, PayloadAad};

// The AAD for a step result binds the execution, the step, and the entry shape.
let aad = PayloadAad::new(ExecutionId::new(), StepId::new(7), EntryKindTag::StepResult, None);

// The canonical encoding is deterministic and injective — the same logical AAD always
// produces the same bytes, and no two distinct AADs collide.
assert_eq!(aad.canonical_bytes(), aad.canonical_bytes());

Structs§

PayloadAad
The associated data bound into a payload seal.

Enums§

CipherError
A failure raised by a PayloadCipher.
EntryKindTag
A Copy discriminator naming the shape of a journal entry, used inside PayloadAad.

Traits§

PayloadCipher
Encrypts and decrypts opaque journal payloads with an AEAD construction.

Functions§

ensure_payload_within_limit
Reject a payload that exceeds max_bytes before any decryption or decode is attempted.