Skip to main content

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//! Separately, the [`ed25519`] module exposes **bare RFC 8032 Ed25519**
51//! (sign/verify, no framing, no PQ component). It exists *only* for byte-level
52//! interoperability with the deployed C2SP transparency-log witness ecosystem
53//! (Go `sumdb/note`, sigsum, transparency-dev, Tessera), which co-signs
54//! checkpoints with raw Ed25519. It is **not** a general-purpose signing API —
55//! use the hybrid PQ [`sign`] for Metamorphic authenticity.
56
57#![forbid(unsafe_code)]
58#![deny(missing_docs)]
59
60pub mod b64;
61pub mod box_seal;
62mod ecc;
63pub mod ed25519;
64pub mod error;
65pub mod hash;
66pub mod hybrid;
67pub mod kdf;
68pub mod keys;
69pub mod recovery;
70pub mod seal;
71pub mod secretbox;
72pub mod sign;
73pub mod suite;
74pub mod vrf;
75
76#[cfg(target_arch = "wasm32")]
77pub mod wasm;
78
79pub use error::CryptoError;
80
81// Re-export the primary public API
82pub use b64::parse_salt_from_key_hash;
83pub use box_seal::{box_seal, box_seal_open};
84pub use ed25519::{
85    ED25519_PUBLIC_KEY_LEN, ED25519_SEED_LEN, ED25519_SIGNATURE_LEN, ed25519_generate_keypair,
86    ed25519_public_key, ed25519_sign, ed25519_verify,
87};
88pub use hash::{sha3_256, sha3_512, sha3_512_with_context, sha256, sha512};
89pub use hybrid::{
90    HybridKeyPair, SecurityLevel, generate_hybrid_keypair, generate_hybrid_keypair_512,
91    generate_hybrid_keypair_1024, generate_hybrid_keypair_suite,
92    generate_hybrid_keypair_with_level, hybrid_open, hybrid_open_with_context, hybrid_seal,
93    hybrid_seal_512, hybrid_seal_1024, hybrid_seal_suite, hybrid_seal_suite_with_context,
94    hybrid_seal_with_level, is_hybrid_ciphertext,
95};
96pub use kdf::derive_session_key;
97pub use keys::{
98    KeyPair, decrypt_private_key, encrypt_private_key, generate_key, generate_keypair,
99    generate_salt,
100};
101pub use recovery::{
102    RecoveryKey, decrypt_private_key_with_recovery, encrypt_private_key_for_recovery,
103    generate_recovery_key, recovery_key_to_secret,
104};
105pub use seal::{
106    seal_for_user, seal_for_user_with_level, seal_for_user_with_suite, unseal_from_user,
107};
108pub use secretbox::{
109    decrypt_secretbox, decrypt_secretbox_to_string, encrypt_secretbox, encrypt_secretbox_string,
110};
111pub use sign::{
112    HybridSignatureKeyPair, SIGN_CONTEXT_V1, SignatureLevel, derive_public_key,
113    generate_signing_keypair, generate_signing_keypair_44, generate_signing_keypair_87,
114    generate_signing_keypair_suite, generate_signing_keypair_with_level, sign, verify,
115};
116pub use suite::{SEAL_CONTEXT_V1, Suite};
117pub use vrf::{
118    ECVRF_EDWARDS25519_SHA512_TAI_SUITE, ECVRF_OUTPUT_LEN, ECVRF_PROOF_LEN, ECVRF_PUBLIC_KEY_LEN,
119    ECVRF_SECRET_KEY_LEN, ecvrf_generate_keypair, ecvrf_proof_to_hash, ecvrf_prove,
120    ecvrf_public_key, ecvrf_verify,
121};