pub struct SecretBytes<const N: usize> { /* private fields */ }Expand description
Fixed-size secret byte storage with automatic sanitization on drop.
On targets with 8-bit atomics, each byte is stored as an AtomicU8.
Atomic stores are observable side effects, giving a safe, dependency-free
clear path without raw pointers or volatile writes. On targets without
8-bit atomics the type remains available through safe core::cell::Cell
storage, but clearing cannot claim the same optimizer resistance as the
atomic path.
§Platform Notes
On targets with 8-bit atomics (target_has_atomic = "8"), this type is
Sync and can be shared across threads for read-only access. Mutating and
clearing operations require &mut self to prevent partially-cleared
multi-byte observations through shared references. On targets without 8-bit
atomics, this type uses core::cell::Cell and is !Sync, so static or
cross-thread sharing patterns that compile on server targets may not compile
on no-atomic embedded targets.
The type deliberately does not implement Clone, Copy, Deref,
AsRef<[u8]>, PartialEq, or secret-printing Debug.
Implementations§
Source§impl<const N: usize> SecretBytes<N>
impl<const N: usize> SecretBytes<N>
Sourcepub fn from_array(bytes: [u8; N]) -> Self
pub fn from_array(bytes: [u8; N]) -> Self
Create a secret from an array, then best-effort clear the input array.
For the strongest move hygiene, prefer SecretBytes::from_fn or
SecretBytes::copy_from_slice so callers can avoid building a normal
byte array first.
Sourcepub fn from_fn(make_byte: impl FnMut(usize) -> u8) -> Self
pub fn from_fn(make_byte: impl FnMut(usize) -> u8) -> Self
Create a secret by producing each byte directly.
This avoids requiring a full temporary [u8; N] at the call boundary.
Sourcepub fn copy_from_slice(&mut self, source: &[u8]) -> Result<(), LengthError>
pub fn copy_from_slice(&mut self, source: &[u8]) -> Result<(), LengthError>
Replace all bytes from a same-length slice.
Sourcepub fn copy_to_slice(&self, destination: &mut [u8]) -> Result<(), LengthError>
pub fn copy_to_slice(&self, destination: &mut [u8]) -> Result<(), LengthError>
Fill a caller-provided destination with a temporary copy of the secret.
Sourcepub fn read_byte(&self, index: usize) -> Option<u8>
pub fn read_byte(&self, index: usize) -> Option<u8>
Read one byte without exposing the whole secret.
Sourcepub fn write_byte(&mut self, index: usize, value: u8) -> Result<(), LengthError>
pub fn write_byte(&mut self, index: usize, value: u8) -> Result<(), LengthError>
Replace one byte.
Sourcepub fn expose_secret<R>(&self, inspect: impl FnOnce(&[u8; N]) -> R) -> R
pub fn expose_secret<R>(&self, inspect: impl FnOnce(&[u8; N]) -> R) -> R
Call a closure with a temporary array copy, then clear that copy.
This is the narrowest safe way to interoperate with APIs requiring
&[u8]. The closure must not retain or return references to the
temporary array; Rust’s borrow checker enforces that part. The closure can
still intentionally copy bytes elsewhere, so use it only at true
cryptographic or protocol boundaries.
If the closure aborts the process, for example under panic = "abort",
Rust destructors do not run and the temporary stack copy cannot be
cleared. On the normal return path the temporary is cleared eagerly
before this method returns; on unwinding panic paths the RAII guard
clears it during unwinding.
Sourcepub fn constant_time_eq(&self, other: &[u8]) -> bool
pub fn constant_time_eq(&self, other: &[u8]) -> bool
Compare against a slice without early exit for equal-length inputs.
Length mismatch returns immediately because the provided slice length is treated as public metadata. Prefer fixed-size inputs where possible.
Sourcepub fn constant_time_eq_secret(&self, other: &Self) -> bool
pub fn constant_time_eq_secret(&self, other: &Self) -> bool
Compare against another secret without early exit.
Sourcepub fn secure_clear(&mut self)
pub fn secure_clear(&mut self)
Clear all bytes now. This is also called from Drop.