stenoxide_core/crypto/mod.rs
1//! Layer 2 — cryptography.
2//!
3//! Password-based key derivation (Argon2id), key expansion into independent
4//! subkeys (HKDF-SHA3-512), authenticated encryption (XChaCha20-Poly1305) and
5//! payload compression. Every type that holds key material implements
6//! `ZeroizeOnDrop`.
7//!
8//! The layer is a one-way chain, and each stage narrows what the next one can
9//! do wrong:
10//!
11//! ```text
12//! password + phash --Argon2id--> MasterKey
13//! --HKDF-SHA3-512--> DerivedKeys { enc_key, nonce, stc_seed }
14//! plaintext --zstd--> compressed --XChaCha20-Poly1305--> ciphertext
15//! ```
16//!
17//! # The second way into the chain
18//!
19//! Behind the `pqc` feature, [`kem`] establishes the master key by ML-KEM-1024
20//! encapsulation instead of by stretching a password:
21//!
22//! ```text
23//! recipient public key --ML-KEM-1024--> shared secret + kem ciphertext
24//! --HKDF-SHA3-512--> MasterKey
25//! --HKDF-SHA3-512--> DerivedKeys { enc_key, nonce, stc_seed }
26//! ```
27//!
28//! The two sources meet at `DerivedKeys` and nowhere earlier, and they are kept
29//! apart by a domain separator of their own; see
30//! [`expand::expand_shared_secret`]. Everything downstream — the cipher, the
31//! associated data, the compression — is the same code in both modes.
32//!
33//! The mode is **experimental** and not compiled into a default build. See
34//! [`kem`] for what is and is not settled about it.
35
36pub mod aead;
37pub mod expand;
38pub mod kdf;
39
40// The text form both key files are written in. Private to the crypto layer:
41// what it encodes is a decision of [`kem`], and nothing outside should be able
42// to armour bytes of its own under one of those labels.
43#[cfg(feature = "pqc")]
44mod armor;
45
46#[cfg(feature = "pqc")]
47pub mod kem;