toolkit_zero/serialization/mod.rs
1//! Struct-to-binary serialization with authenticated encryption.
2//!
3//! This module converts any [`bincode`]-encodable value into an opaque,
4//! authenticated byte blob and back, using **ChaCha20-Poly1305** (IETF AEAD).
5//! A fresh random 12-byte nonce is generated for every [`seal`] call, so
6//! ciphertexts are non-deterministic even for identical plaintext and key.
7//!
8//! # What is guaranteed
9//!
10//! * **Confidentiality.** The ciphertext reveals nothing about the plaintext
11//! without the key.
12//! * **Integrity and authenticity.** The Poly1305 tag detects any bit-level
13//! modification; [`open`] returns an error on tampered or truncated blobs.
14//! * **Semantic security.** The random nonce ensures that encrypting the same
15//! value twice produces different ciphertexts, preventing chosen-plaintext
16//! attacks.
17//! * **No magic bytes / constant header.** Every output byte depends on the
18//! key and a fresh nonce; there is no static recognisable prefix.
19//!
20//! # Format
21//!
22//! ```text
23//! blob = nonce (12 B) ‖ AEAD_ciphertext (bincode(value)) ‖ Poly1305 tag (16 B)
24//! ```
25//!
26//! # Default key
27//!
28//! When no key is supplied, the string `"serialization/deserialization"` is
29//! used.
30//!
31//! # Example
32//!
33//! ```no_run
34//! use toolkit_zero::serialization::{seal, open, Encode, Decode};
35//!
36//! #[derive(Encode, Decode, Debug, PartialEq)]
37//! struct Point { x: f64, y: f64 }
38//!
39//! let p = Point { x: 1.5, y: -3.0 };
40//!
41//! // default key — string literals work directly
42//! let blob = seal(&p, None::<&str>).unwrap();
43//! let back: Point = open(&blob, None::<&str>).unwrap();
44//! assert_eq!(p, back);
45//!
46//! // explicit key — str literals or String are both accepted
47//! let blob2 = seal(&p, Some("my secret key")).unwrap();
48//! let back2: Point = open(&blob2, Some("my secret key")).unwrap();
49//! assert_eq!(p, back2);
50//! ```
51
52mod aead;
53
54pub use aead::{seal, open, SerializationError};
55pub use bincode::{Encode, Decode};
56// Re-exported so that `#[serializable]` users don't need a direct `bincode` dep.
57// bincode's proc-macro derive generates code that resolves `bincode::` against
58// this path (via `#[bincode(crate = "::toolkit_zero::serialization::bincode")]`
59// injected by the macro).
60pub use bincode;
61pub use toolkit_zero_macros::{serializable, serialize, deserialize};
62
63#[cfg(feature = "backend-deps")]
64pub mod backend_deps;