secure_gate/traits/expose_secret.rs
1//! # Secret Exposure Traits
2//!
3//! This module defines traits for polymorphic secret access with controlled mutability and metadata.
4//! These traits enable writing generic code that works across different secret wrapper types
5//! while enforcing security guarantees.
6//!
7//! ## Key Traits
8//!
9//! - [`ExposeSecret`]: Read-only access to secret values including metadata
10//!
11//! ## Security Model
12//!
13//! - **Full access**: Core wrappers ([`crate::Fixed`], [`crate::Dynamic`]) implement [`ExposeSecret`], with mutable variants implementing [`crate::ExposeSecretMut`]
14//! - **Read-only**: Encoding wrappers only implement [`ExposeSecret`] to prevent mutation
15//! - **Zero-cost**: All implementations use `#[inline(always)]`
16//!
17/// Trait for read-only access to secrets, including metadata.
18///
19/// ## Usage
20///
21/// Import these traits to access secret values and their metadata ergonomically.
22///
23/// Import this to enable `.with_secret()`, `.expose_secret()`, `.len()`, and `.is_empty()`.
24/// For mutable access, see [`crate::ExposeSecretMut`].
25///
26/// ## Security Note
27///
28/// Prefer `with_secret` for scoped access to avoid accidental leaks through long-lived borrows.
29/// `expose_secret` is provided for cases where a direct reference is needed, but use with caution.
30pub trait ExposeSecret {
31 /// The inner secret type being exposed.
32 ///
33 /// This can be a sized type (like `[u8; N]`) or unsized (like `str` or `[u8]`).
34 type Inner: ?Sized;
35
36 /// Provide scoped read-only access to the secret.
37 ///
38 /// This is the preferred method for accessing secrets, as it prevents accidental leaks
39 /// through long-lived borrows. The closure receives a reference to the inner secret
40 /// and returns a value.
41 ///
42 /// # Examples
43 ///
44 /// ```
45 /// use secure_gate::{Fixed, ExposeSecret};
46 /// let secret = Fixed::new([42u8; 4]);
47 /// let sum: u32 = secret.with_secret(|bytes| bytes.iter().map(|&b| b as u32).sum());
48 /// assert_eq!(sum, 42 * 4);
49 /// ```
50 fn with_secret<F, R>(&self, f: F) -> R
51 where
52 F: FnOnce(&Self::Inner) -> R;
53
54 /// Expose the secret for read-only access.
55 ///
56 /// # Security Warning
57 ///
58 /// This returns a direct reference that can be accidentally leaked. Prefer `with_secret`
59 /// for most use cases to ensure the secret is only accessed within a controlled scope.
60 fn expose_secret(&self) -> &Self::Inner;
61
62 /// Returns the length of the secret.
63 fn len(&self) -> usize;
64
65 /// Returns true if the secret is empty.
66 #[inline(always)]
67 fn is_empty(&self) -> bool {
68 self.len() == 0
69 }
70}