Expand description
An AEAD that chooses its own nonces.
Every Aead takes a nonce from its caller, and under AES-GCM or
ChaCha20-Poly1305 a nonce used twice under one key is catastrophic: GCM
leaks its authentication subkey, ChaCha20 XORs the two plaintexts. The rule
is easy to state and easy to break, because nothing in seal_detached’s
signature tells you that the bytes you pass it are the dangerous ones.
Sealer takes the nonce out of the caller’s hands. It builds each one as
SP 800-38D section 8.2.1’s deterministic construction does: a 4-byte fixed
field naming the sender, then a 64-bit invocation counter, big-endian. It
returns the nonce it used, so the receiver can be sent it. It refuses rather
than wrap when the counter runs out.
Opener is the receiving side. It accepts only the sender’s fixed field
and only counters it has not passed, so a replayed or reordered message is
refused before the AEAD runs.
use ic_cipher::{Aes256Gcm, sealer::{Opener, Sealer}};
// A key for this session only: from a key exchange and a KDF, not a constant.
let key = [0x2a; 32];
let mut tx = Sealer::<Aes256Gcm>::new(&key, *b"c->s")?;
let mut rx = Opener::<Aes256Gcm>::new(&key, *b"c->s")?;
let mut msg = *b"ship it";
let mut tag = [0u8; 16];
let nonce = tx.seal(b"header", &mut msg, &mut tag)?;
rx.open(&nonce, b"header", &mut msg, &tag)?;
assert_eq!(&msg, b"ship it");
// The same message again is a replay, and is refused.
assert!(rx.open(&nonce, b"header", &mut msg, &tag).is_err());§What the counter cannot know
A counter is unique only within the object that holds it. Two Sealers on
the same key and fixed field both start at zero and reuse every nonce, and a
process that restarts and builds a new one does the same. So:
- Use a key that lives no longer than its
Sealer: one derived for the session, as TLS 1.3 and HPKE do. A long-lived key needs the counter persisted and restored withSealer::resume, or a nonce-misuse-resistant AEAD such as AES-256-GCM-SIV. - Give every sender under one key its own fixed field, such as one per direction. Better still, give each direction its own key.
The 12-byte nonce is required: it is the length every AEAD here takes and the one SP 800-38D’s construction is defined for.
Structs§
- Opener
- Opens messages from one
Sealer, refusing replays and reordering. - Sealer
- Seals messages under nonces it builds itself, each used once.