Skip to main content

secure_gate/traits/
cloneable_secret.rs

1//! Opt-in marker trait for safe, explicit cloning of secrets.
2//!
3//! This trait serves as a deliberate opt-in mechanism to enable the `Clone`
4//! implementation on secret wrapper types (`Fixed<T>`, `Dynamic<T>`, aliases)
5//! while preserving core security invariants:
6//!
7//! - **Zeroization preserved**: All clones zeroize their contents on drop.
8//! - **No accidental cloning**: Cloning is impossible unless the inner type
9//!   explicitly implements `CloneableSecret`.
10//! - **Auditable risk**: Cloning increases the exposure surface (more copies
11//!   of the secret exist in memory); this trait forces developers to acknowledge
12//!   and accept that risk.
13//!
14//! Requires the `cloneable` feature to be enabled.
15//!
16//! # When to Use
17//!
18//! Implement `CloneableSecret` on inner types only when duplication is
19//! **truly necessary** (e.g., session keys passed to multiple threads,
20//! backup/export scenarios). Prefer move semantics or single-instance ownership
21//! whenever possible to minimize attack surface.
22//!
23//! # Example
24//!
25//! ```rust
26//! use secure_gate::{CloneableSecret, Fixed, RevealSecret};
27//! use zeroize::Zeroize;
28//!
29//! #[derive(Clone)]
30//! struct SessionKey([u8; 32]);
31//!
32//! impl Zeroize for SessionKey {
33//!     fn zeroize(&mut self) { self.0.zeroize(); }
34//! }
35//!
36//! // Every impl is a deliberate security decision — audit all usages.
37//! impl CloneableSecret for SessionKey {}
38//!
39//! let original = Fixed::new(SessionKey([0u8; 32]));
40//! let copy = original.clone();   // Opt-in cloning: each copy is independently zeroized.
41//! drop(original);  // zeroized on drop
42//! drop(copy);      // independently zeroized on drop
43//! ```
44//!
45//! # Security Notes
46//!
47//! - Cloning **does not** bypass zeroization — **every** copy is independently zeroized on drop.
48//!   However, each clone **increases the number of simultaneous in-memory copies**, expanding
49//!   the window for memory-extraction attacks (cold-boot, scraping, etc.).
50//! - Audit all `CloneableSecret` impls to ensure the inner type correctly implements
51//!   `Clone` and `Zeroize`.
52//!
53//! This trait is a **marker only** — it has no methods and adds no runtime behavior.
54//! It exists solely to gate the `Clone` impl on wrapper types.
55
56/// Marker trait that opts a secret type into cloning.
57///
58/// No methods — its only purpose is to gate the `Clone` impl on
59/// [`Fixed<T>`](crate::Fixed) and [`Dynamic<T>`](crate::Dynamic).
60/// Requires the `cloneable` feature.
61#[cfg(feature = "cloneable")]
62pub trait CloneableSecret: Clone + zeroize::Zeroize {}