Skip to main content

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}