metamorphic_crypto/lib.rs
1//! # metamorphic-crypto
2//!
3//! Zero-knowledge end-to-end encryption core for the Metamorphic platform.
4//!
5//! This library implements the cryptographic operations required by all Metamorphic
6//! clients (web/WASM, iOS/UniFFI, Android/UniFFI). It produces byte-compatible
7//! ciphertext with the existing JavaScript implementation so that data encrypted
8//! by one client can be decrypted by any other.
9//!
10//! ## Security guarantees
11//!
12//! - All secret key material is [`Zeroize`]-on-drop
13//! - No `unsafe` code
14//! - Constant-time comparisons via the underlying RustCrypto crates
15//! - Randomness sourced directly from the OS CSPRNG ([`getrandom`])
16//!
17//! ## Ciphertext formats
18//!
19//! The legacy `Suite::Hybrid` (default) formats are byte-for-byte unchanged. The
20//! opt-in CNSA 2.0 suites use an AES-256-GCM envelope keyed by
21//! `HKDF-SHA512(info = suite_tag || context_label)` (see [`suite`]); the
22//! `nonce (12B) || ct || gcm_tag (16B)` portion is the AEAD output.
23//!
24//! | Format | Layout |
25//! |--------|--------|
26//! | Secretbox | `nonce (24B) \|\| ciphertext (len + 16B MAC)` |
27//! | box_seal | `ephemeral_pk (32B) \|\| box ciphertext` |
28//! | Hybrid v1 (Cat-1) | `0x01 \|\| ML-KEM-512 ct (768B) \|\| X25519 eph pk (32B) \|\| nonce (24B) \|\| secretbox ct` |
29//! | Hybrid v2 (Cat-3) | `0x02 \|\| ML-KEM-768 ct (1088B) \|\| X25519 eph pk (32B) \|\| nonce (24B) \|\| secretbox ct` |
30//! | Hybrid v3 (Cat-5) | `0x03 \|\| ML-KEM-1024 ct (1568B) \|\| X25519 eph pk (32B) \|\| nonce (24B) \|\| secretbox ct` |
31//! | PureCnsa2 (Cat-5) | `0x10 \|\| ML-KEM-1024 ct (1568B) \|\| nonce (12B) \|\| ct \|\| gcm_tag (16B)` |
32//! | HybridMatched (Cat-3) | `0x13 \|\| ML-KEM-768 ct (1088B) \|\| X448 eph pk (56B) \|\| nonce (12B) \|\| ct \|\| gcm_tag (16B)` |
33//! | HybridMatched (Cat-5) | `0x14 \|\| ML-KEM-1024 ct (1568B) \|\| P-521 eph pk (133B) \|\| nonce (12B) \|\| ct \|\| gcm_tag (16B)` |
34//!
35//! ## Signature formats
36//!
37//! The default `Suite::Hybrid` is a composite ML-DSA + Ed25519 signature with
38//! strict-AND verification. The opt-in CNSA 2.0 suites place the fixed-size
39//! classical component first (so the variable ML-DSA tail needs no length
40//! prefix) and reuse the same I2OSP domain-separation framing. `PureCnsa2` has
41//! no classical component. All are strict-AND verified.
42//!
43//! | Suite (level) | signature | public_key | secret_key |
44//! |---------------|-----------|------------|------------|
45//! | Hybrid (Cat-2/3/5) | `tag \|\| ed25519_sig (64B) \|\| ml_dsa_sig` | `tag \|\| ed25519_pk (32B) \|\| ml_dsa_pk` | `tag \|\| ed25519_seed (32B) \|\| ml_dsa_seed (32B)` |
46//! | HybridMatched (Cat-3) | `0x13 \|\| ed448_sig (114B) \|\| ml_dsa65_sig` | `0x13 \|\| ed448_pk (57B) \|\| ml_dsa65_pk` | `0x13 \|\| ed448_seed (57B) \|\| ml_dsa_seed (32B)` |
47//! | HybridMatched (Cat-5) | `0x14 \|\| ecdsa_p521_sig (132B) \|\| ml_dsa87_sig` | `0x14 \|\| p521_pk (133B) \|\| ml_dsa87_pk` | `0x14 \|\| p521_seed (66B) \|\| ml_dsa_seed (32B)` |
48//! | PureCnsa2 (Cat-5) | `0x10 \|\| ml_dsa87_sig` | `0x10 \|\| ml_dsa87_pk` | `0x10 \|\| ml_dsa_seed (32B)` |
49
50#![forbid(unsafe_code)]
51#![deny(missing_docs)]
52
53pub mod b64;
54pub mod box_seal;
55mod ecc;
56pub mod error;
57pub mod hash;
58pub mod hybrid;
59pub mod kdf;
60pub mod keys;
61pub mod recovery;
62pub mod seal;
63pub mod secretbox;
64pub mod sign;
65pub mod suite;
66
67#[cfg(target_arch = "wasm32")]
68pub mod wasm;
69
70pub use error::CryptoError;
71
72// Re-export the primary public API
73pub use b64::parse_salt_from_key_hash;
74pub use box_seal::{box_seal, box_seal_open};
75pub use hash::{sha3_256, sha3_512, sha3_512_with_context, sha256, sha512};
76pub use hybrid::{
77 HybridKeyPair, SecurityLevel, generate_hybrid_keypair, generate_hybrid_keypair_512,
78 generate_hybrid_keypair_1024, generate_hybrid_keypair_suite,
79 generate_hybrid_keypair_with_level, hybrid_open, hybrid_open_with_context, hybrid_seal,
80 hybrid_seal_512, hybrid_seal_1024, hybrid_seal_suite, hybrid_seal_suite_with_context,
81 hybrid_seal_with_level, is_hybrid_ciphertext,
82};
83pub use kdf::derive_session_key;
84pub use keys::{
85 KeyPair, decrypt_private_key, encrypt_private_key, generate_key, generate_keypair,
86 generate_salt,
87};
88pub use recovery::{
89 RecoveryKey, decrypt_private_key_with_recovery, encrypt_private_key_for_recovery,
90 generate_recovery_key, recovery_key_to_secret,
91};
92pub use seal::{
93 seal_for_user, seal_for_user_with_level, seal_for_user_with_suite, unseal_from_user,
94};
95pub use secretbox::{
96 decrypt_secretbox, decrypt_secretbox_to_string, encrypt_secretbox, encrypt_secretbox_string,
97};
98pub use sign::{
99 HybridSignatureKeyPair, SIGN_CONTEXT_V1, SignatureLevel, derive_public_key,
100 generate_signing_keypair, generate_signing_keypair_44, generate_signing_keypair_87,
101 generate_signing_keypair_suite, generate_signing_keypair_with_level, sign, verify,
102};
103pub use suite::{SEAL_CONTEXT_V1, Suite};