Expand description
§CryptGuard v2
§Introduction
Current release status: 2.0.0. The safe-default Phase 4 upgrade is
implemented, externally consumer-tested, and test-green. Before publishing,
close the release hygiene gates tracked in guides/release-readiness.md.
CryptGuard is a post-quantum sealing library built on the NIST FIPS 203/204/205 final standards. The primary flow is:
ML-KEM (FIPS 203) -> HKDF -> Authenticated Envelope (HPKE-shaped, RFC 9180)The v2 line replaces the old pqcrypto Kyber / Falcon / Dilithium path with
FIPS-final ML-KEM, ML-DSA, and SLH-DSA as the default. The old path is still
available behind --features legacy-pqclean for reading data created with v1.x.
§Key Features
- ML-KEM-512/768/1024 (FIPS 203) for key encapsulation.
- HKDF-SHA-256/512 key schedule with domain-separated labels following the NIST SP 800-227 direction: the shared secret is never used raw as a cipher key.
- CGv2 Authenticated Envelope: one self-describing blob
{ header, kem_ciphertext, nonce, ciphertext }— nonce is internal, callers never juggle it separately. - XChaCha20-Poly1305 and AES-256-GCM-SIV authenticated AEAD.
- ML-DSA-44/65/87 (FIPS 204) and SLH-DSA (FIPS 205) digital signatures.
- Compile-enforced content-axis typestate: calling
encrypt_fileon aMessageinstance is a compile error (E0599). - Legacy Kyber / Falcon / Dilithium kept behind
legacy-pqcleanfeature so v1.x data remains decryptable.
§Safe Default: Encryptor / Decryptor
The primary entry point is the staged-builder pair. The safe flow has no
manual nonce handling and no tuple unpacking; current builders still accept
key bytes while the lower kem module keeps typed key roles.
use crypt_guard::{Encryptor, Decryptor};
use crypt_guard::{MlKem768, XChaCha20Poly1305};
use crypt_guard::kem::{KemBackend, ml_kem::MlKem768Impl};
use crypt_guard::kem::backend::OsRng;
let mut rng = OsRng;
let (public_key, secret_key) = MlKem768Impl::keypair(&mut rng)?;
// Seal: ML-KEM encapsulate -> HKDF -> XChaCha20-Poly1305
let envelope = Encryptor::<MlKem768, XChaCha20Poly1305>::new()
.recipient(public_key.as_ref().to_vec())
.plaintext(b"hello post-quantum world")
.seal()?;
// Open: ML-KEM decapsulate -> HKDF -> AEAD verify + decrypt
let plaintext = Decryptor::<MlKem768, XChaCha20Poly1305>::new()
.secret_key(secret_key.as_ref().to_vec())
.open(&envelope)?;
assert_eq!(plaintext, b"hello post-quantum world");§Protocol: HPKE-Shaped CGv2 Envelope
The envelope structure mirrors HPKE (RFC 9180) as deployed by Cloudflare,
AWS, and Google for post-quantum TLS key establishment. The sender output is
a single blob, not a (ciphertext, kem_secret) tuple:
Sender:
(kem_ct, shared_secret) = ML-KEM.Encapsulate(recipient_pk)
session_key = HKDF(ikm=shared_secret, salt=kem_ct,
info="crypt_guard:v2:aead:<alg>")
ciphertext = AEAD.Seal(session_key, nonce, aad, plaintext)
envelope = { header, kem_ct, nonce, ciphertext }
Receiver:
shared_secret = ML-KEM.Decapsulate(kem_ct, recipient_sk)
session_key = HKDF(same params)
plaintext = AEAD.Open(session_key, nonce, aad, ciphertext)The shared secret is zeroized immediately after key derivation
(NIST SP 800-227). The header carries kem_id, kdf_id, aead_id
so the envelope is self-describing and forwards-compatible.
§Typestate Design: Kyber<Process, Size, Content, Algorithm>
The underlying type encodes four axes at the type level. Mismatching axes (wrong process direction, wrong content kind, wrong cipher) is a compile error, not a runtime panic:
| Axis | Variants |
|---|---|
| Process | Encryption, Decryption |
| Size | MlKem512, MlKem768, MlKem1024 |
| Content | Data, Message, Files |
| Algorithm | XChaCha20Poly1305, AesGcmSiv, … |
The Encryptor/Decryptor builders expose the Data content path. The
full Kyber<P,S,C,A> API is available for direct use when you need
Message or Files content handling.
§Feature Flags
| Flag | Default | Description |
|---|---|---|
ml-kem-backend | yes | ML-KEM-512/768/1024 (FIPS 203) |
ml-dsa-backend | yes | ML-DSA-44/65/87 (FIPS 204) |
sign-slhdsa | no | SLH-DSA (FIPS 205) |
aes-ctr | no | AES-CTR stream cipher |
aes-xts | no | AES-XTS disk encryption |
archive | no | tar/xz/gz archive helpers |
legacy-pqclean | no | Legacy Kyber/Falcon/Dilithium + old tuple API |
§Legacy Compatibility
Data encrypted with crypt_guard v1.x can still be decrypted by enabling
the legacy-pqclean feature. The old Kyber<Encryption, Kyber1024, Message, AES>
types, the encryption! / decryption! macros, the kyber_keypair! macro,
and the tuple-returning encrypt_msg / decrypt_msg functions are all
preserved under the legacy module.
// Legacy path — requires --features legacy-pqclean
use crypt_guard::{*, error::*};
let (public_key, secret_key) = kyber_keypair!(1024);
let (ciphertext, kyber_secret) = encryption!(
public_key.to_owned(), 1024,
b"hello".to_vec(), "passphrase", AES
)?;
let plaintext = decryption!(
secret_key.to_owned(), 1024,
ciphertext, "passphrase", kyber_secret, AES
)?;§References
Re-exports§
pub use crate::key_control::file;pub use api::open as hpke_open;pub use api::seal as hpke_seal;pub use api::AuthenticatedAead;pub use api::Decryptor;pub use api::DecryptorBuilder;pub use api::Encryptor;pub use api::EncryptorBuilder;pub use api::MissingPlaintext;pub use api::MissingRecipient;pub use api::MissingSecretKey;pub use api::WithPlaintext;pub use api::WithRecipient;pub use api::WithSecretKey;pub use markers::AesGcmSiv;pub use markers::XChaCha20Poly1305;pub use protocol::Envelope;pub use crate::markers::AesCtr;pub use crate::markers::AesGcmSiv;pub use crate::markers::AesXts;pub use crate::markers::Data;pub use crate::markers::Decryption;pub use crate::markers::Encryption;pub use crate::markers::Files;pub use crate::markers::Message;pub use crate::markers::XChaCha20;pub use crate::markers::XChaCha20Poly1305;pub use crate::markers::AES;pub use crate::key_control::*;pub use crate::log::*;
Modules§
- api
- Safe default public API over the Phase 3 ML-KEM + HKDF + AEAD envelope path. Safe public API over the Phase 3 CGv2 envelope protocol.
- builder
- Builder-style API for encryption/decryption, keygen, and signature flows Fluent builder API over the legacy Kyber encryption, decryption, and signing macros.
- cipher_
xchacha - XChaCha20 stream cipher implementation.
- cipher_
xchacha_ poly - XChaCha20-Poly1305 AEAD implementation.
- cryptography
- Cryptographic related functionalitys, enums structs and modules
- error
- Error types
Crate-wide error types for
crypt_guard. - hub
- Phase 3 hub module (src/core/hub/): EncryptFunctions + DecryptFunctions traits,
FIPS primary size markers MlKem512/768/1024, ML-KEM + HKDF + Envelope-wired cipher impls.
Hub module:
Kyber<P, K, D, C>four-axis typestate, KEM variant traits, and cipher markers. - kdf
- HKDF-SHA256/512 key schedule with domain separation. HKDF-based key schedule with domain separation (Phase 2 — always compiled).
- kem
- ML-KEM backend trait and ML-KEM-512/768/1024 implementations (FIPS 203). KEM (Key Encapsulation Mechanism) backend trait and ML-KEM implementations.
- key_
control - File and Key related functionalitys, enums structs and modules Typed key and file-metadata primitives for the key-control subsystem.
- kyber
- Legacy hub module (src/core/kyber/): keeps KyberData, Kyber struct, KyberFunctions trait,
KyberSizeVariant, deprecated size markers, and key_controler (legacy-pqclean).
Hub module:
Kyber<P, K, D, C>four-axis typestate, KEM variant traits, and cipher markers. - log
- Logging related functionalitys
Tracing-based logging surface for
crypt_guard. - markers
- Shared zero-sized-type axis markers (Encryption/Decryption, Files/Message/Data, cipher markers).
Re-exported here so
crate::*continues to expose them. Shared zero-sized-type (ZST) axis markers used acrosscore/,legacy/, and the public API. - protocol
- CGv2 authenticated envelope protocol (Phase 3).
CGv2 authenticated envelope protocol (
src/protocol/). - sign
- SignAlgorithm trait and ML-DSA/SLH-DSA implementations (FIPS 204/205). Digital signature backend trait and FIPS 204/205 implementations.
- utils
Macros§
- archive
- Macro to archive a directory or file.
- archive_
util - Macro for archiving and extracting directories or files.
- concat_
cipher - decrypt_
file - Macro for encryption of a file, taking a Kyber decryption instance, a
PathBufas well as a passphrase and ciphertext as arguments - decryption
- encrypt_
file - Macro for encryption of a file, taking a Kyber decryption instance, a
PathBufas well as a passphrase and ciphertext as arguments - encryption
- extract
- Macro to extract a
.tar.xzarchive. - impl_
kyber_ cipher - Generate
EncryptFunctions+DecryptFunctionsimpls for one cipher marker. - log_
activity - signature
- split_
cipher - verify
- write_
log
Structs§
- Kyber
- Represents a generic Kyber structure with templated parameters for process status, Kyber size, content status, and algorithm parameter.
- Kyber512
- Legacy KEM size marker: Kyber-512.
- Kyber768
- Legacy KEM size marker: Kyber-768.
- Kyber1024
- Legacy KEM size marker: Kyber-1024.
- Kyber
Data - Represents the data structure for Kyber algorithm, including key and nonce.
- MlKem512
- Primary KEM size marker: ML-KEM-512 (FIPS 203, security category 1).
- MlKem768
- Primary KEM size marker: ML-KEM-768 (FIPS 203, security category 3 — recommended).
- MlKem1024
- Primary KEM size marker: ML-KEM-1024 (FIPS 203, security category 5).
Enums§
- Kyber
Variant - Enum representing Kyber variants.
Traits§
- Cryptographic
Functions - Abstract encrypt/decrypt trait.
- Decrypt
Data - Decrypt the byte ciphertext carried by an
Envelope. - Decrypt
File - Decrypt the file ciphertext carried by an
Envelope. - Decrypt
Text - Decrypt the message ciphertext carried by an
Envelope. - Encrypt
Data - Encrypt arbitrary bytes into an authenticated
Envelope. - Encrypt
File - Encrypt the contents of a file into an authenticated
Envelope. - Encrypt
Text - Encrypt a UTF-8 string message into an authenticated
Envelope. - Kyber
Functions - Trait for Kyber cryptographic functions.
- Kyber
Size Variant - Trait to specify Kyber size variants.
Functions§
- activate_
log - Function activating the log, it takes one arg:
&strwhich represents the location of the logfile