pub struct Dynamic<T: ?Sized + Zeroize> { /* private fields */ }Expand description
Heap-allocated secret wrapper with explicit access and automatic zeroization on drop.
Requires alloc feature. Inner type must implement Zeroize.
Zero-cost heap-allocated wrapper for variable-length secrets.
Requires alloc. Inner type must implement Zeroize for automatic zeroization on drop
(including spare capacity in Vec/String).
No Deref, AsRef, or Copy by default — all access requires
expose_secret() or
with_secret() (scoped, preferred).
For the common concrete types, Dynamic::<Vec<u8>>::new_with and
Dynamic::<String>::new_with are the matching scoped constructors —
closures that write directly into the wrapper. new(value) remains
available as the ergonomic default. Debug always prints [REDACTED].
Implementations§
Source§impl<T: ?Sized + Zeroize> Dynamic<T>
impl<T: ?Sized + Zeroize> Dynamic<T>
Sourcepub fn new<U>(value: U) -> Self
pub fn new<U>(value: U) -> Self
Wraps value in a Box<T> and returns a Dynamic<T>.
Accepts any type that implements Into<Box<T>> — including owned values,
Box<T>, String, Vec<u8>, &str (via the blanket From<&str> impl), etc.
Equivalent to Dynamic::from(value) — #[doc(alias = "from")] is set so both
names appear in docs.rs search.
Requires the alloc feature (which Dynamic<T> itself always requires).
Source§impl Dynamic<Vec<u8>>
impl Dynamic<Vec<u8>>
Sourcepub fn to_hex(&self) -> String
pub fn to_hex(&self) -> String
Encodes the secret bytes as a lowercase hex string.
Delegates to ToHex::to_hex on the inner Vec<u8>.
Requires the encoding-hex feature.
Sourcepub fn to_hex_upper(&self) -> String
pub fn to_hex_upper(&self) -> String
Encodes the secret bytes as an uppercase hex string.
Delegates to ToHex::to_hex_upper on the inner Vec<u8>.
Requires the encoding-hex feature.
Sourcepub fn to_base64url(&self) -> String
pub fn to_base64url(&self) -> String
Encodes the secret bytes as an unpadded Base64url string.
Delegates to ToBase64Url::to_base64url on the inner Vec<u8>.
Requires the encoding-base64 feature.
Source§impl Dynamic<String>
impl Dynamic<String>
Sourcepub fn new_with<F>(f: F) -> Self
pub fn new_with<F>(f: F) -> Self
Closure-based constructor for consistent API with Fixed::new_with.
The actual secret data is allocated on the heap; this method exists
for consistent security-first construction idiom across the crate.
Source§impl Dynamic<Vec<u8>>
impl Dynamic<Vec<u8>>
Sourcepub fn from_random(len: usize) -> Self
pub fn from_random(len: usize) -> Self
Fills a new Vec<u8> with len cryptographically secure random bytes and wraps it.
Uses the system RNG (OsRng) via TryRngCore::try_fill_bytes.
In rand 0.9, OsRng is a zero-sized handle to the OS generator (not user-seedable). Requires the rand
feature (and alloc, which Dynamic<Vec<u8>> always needs).
§Panics
Panics if the system RNG fails to provide bytes (TryRngCore::try_fill_bytes
returns Err). This is treated as a fatal environment error.
§Examples
use secure_gate::{Dynamic, RevealSecret};
let nonce: Dynamic<Vec<u8>> = Dynamic::from_random(24);
assert_eq!(nonce.len(), 24);Sourcepub fn from_rng<R: TryRngCore + TryCryptoRng>(
len: usize,
rng: &mut R,
) -> Result<Self, R::Error>
pub fn from_rng<R: TryRngCore + TryCryptoRng>( len: usize, rng: &mut R, ) -> Result<Self, R::Error>
Allocates a Vec<u8> of length len, fills it from rng, and wraps it.
Accepts any TryCryptoRng + TryRngCore.
Pass OsRng for the same system entropy as from_random
with a fallible interface. Do not use OsRng for deterministic tests — in rand 0.9 it is a
unit struct backed by the OS and is not seedable; use a seedable PRNG such as
StdRng with SeedableRng instead. Requires the rand
feature and alloc (implicit — Dynamic<T> itself requires it).
§Errors
Returns R::Error if try_fill_bytes fails.
§Examples
System RNG (same source as from_random, Result-based):
use rand::rngs::OsRng;
use secure_gate::Dynamic;
let nonce: Dynamic<Vec<u8>> = Dynamic::from_rng(24, &mut OsRng).expect("rng fill");Deterministic fill (tests) with a seedable generator:
use rand::rngs::StdRng;
use rand::SeedableRng;
use secure_gate::Dynamic;
let mut rng = StdRng::from_seed([9u8; 32]);
let nonce: Dynamic<Vec<u8>> = Dynamic::from_rng(24, &mut rng).expect("rng fill");Source§impl Dynamic<Vec<u8>>
impl Dynamic<Vec<u8>>
Sourcepub fn try_from_hex(s: &str) -> Result<Self, HexError>
pub fn try_from_hex(s: &str) -> Result<Self, HexError>
Decodes a lowercase hex string into Dynamic<Vec<u8>>.
The decoded buffer is kept inside a Zeroizing wrapper until after the
Box allocation completes, guaranteeing zeroization even on OOM panic.
Source§impl Dynamic<Vec<u8>>
impl Dynamic<Vec<u8>>
Sourcepub fn try_from_base64url(s: &str) -> Result<Self, Base64Error>
pub fn try_from_base64url(s: &str) -> Result<Self, Base64Error>
Decodes a Base64url (unpadded) string into Dynamic<Vec<u8>>.
The decoded buffer is kept inside a Zeroizing wrapper until after the
Box allocation completes, guaranteeing zeroization even on OOM panic.
Source§impl Dynamic<Vec<u8>>
impl Dynamic<Vec<u8>>
Sourcepub fn try_from_bech32_unchecked(s: &str) -> Result<Self, Bech32Error>
pub fn try_from_bech32_unchecked(s: &str) -> Result<Self, Bech32Error>
Decodes a Bech32 (BIP-173) string into Dynamic<Vec<u8>>.
The decoded buffer is kept inside a Zeroizing wrapper until after the
Box allocation completes, guaranteeing zeroization even on OOM panic.
§Warning
The HRP is not validated — any HRP will be accepted as long as the checksum
is valid. For security-critical code where cross-protocol confusion must be
prevented, use try_from_bech32.
Sourcepub fn try_from_bech32(s: &str, expected_hrp: &str) -> Result<Self, Bech32Error>
pub fn try_from_bech32(s: &str, expected_hrp: &str) -> Result<Self, Bech32Error>
Decodes a Bech32 (BIP-173) string into Dynamic<Vec<u8>>, validating that the HRP
matches expected_hrp (case-insensitive).
The decoded buffer is kept inside a Zeroizing wrapper until after the
Box allocation completes, guaranteeing zeroization even on OOM panic.
Prefer this over try_from_bech32_unchecked in
security-critical code to prevent cross-protocol confusion attacks.
Source§impl Dynamic<Vec<u8>>
impl Dynamic<Vec<u8>>
Sourcepub fn try_from_bech32m_unchecked(s: &str) -> Result<Self, Bech32Error>
pub fn try_from_bech32m_unchecked(s: &str) -> Result<Self, Bech32Error>
Decodes a Bech32m (BIP-350) string into Dynamic<Vec<u8>>.
The decoded buffer is kept inside a Zeroizing wrapper until after the
Box allocation completes, guaranteeing zeroization even on OOM panic.
§Warning
The HRP is not validated — any HRP will be accepted as long as the checksum
is valid. For security-critical code where cross-protocol confusion must be
prevented, use try_from_bech32m.
Sourcepub fn try_from_bech32m(
s: &str,
expected_hrp: &str,
) -> Result<Self, Bech32Error>
pub fn try_from_bech32m( s: &str, expected_hrp: &str, ) -> Result<Self, Bech32Error>
Decodes a Bech32m (BIP-350) string into Dynamic<Vec<u8>>, validating that the HRP
matches expected_hrp (case-insensitive).
The decoded buffer is kept inside a Zeroizing wrapper until after the
Box allocation completes, guaranteeing zeroization even on OOM panic.
Prefer this over try_from_bech32m_unchecked in
security-critical code to prevent cross-protocol confusion attacks.
Source§impl Dynamic<Vec<u8>>
impl Dynamic<Vec<u8>>
Sourcepub fn deserialize_with_limit<'de, D>(
deserializer: D,
limit: usize,
) -> Result<Self, D::Error>where
D: Deserializer<'de>,
pub fn deserialize_with_limit<'de, D>(
deserializer: D,
limit: usize,
) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Deserializes into Dynamic<Vec<u8>>, rejecting payloads larger than limit bytes.
The standard serde::Deserialize impl calls this with MAX_DESERIALIZE_BYTES.
Use this method directly when you need a tighter or looser ceiling.
The intermediate buffer is kept inside a Zeroizing wrapper until after the Box
allocation completes, guaranteeing zeroization even on OOM panic. Oversized buffers
are also zeroized before the error is returned.
Important: this limit is enforced after the upstream deserializer has fully materialized the payload. It is a result-length acceptance bound, not a pre-allocation DoS guard. For untrusted input, enforce size limits at the transport or parser layer upstream.
Source§impl Dynamic<String>
impl Dynamic<String>
Sourcepub fn deserialize_with_limit<'de, D>(
deserializer: D,
limit: usize,
) -> Result<Self, D::Error>where
D: Deserializer<'de>,
pub fn deserialize_with_limit<'de, D>(
deserializer: D,
limit: usize,
) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Deserializes into Dynamic<String>, rejecting payloads larger than limit bytes.
The standard serde::Deserialize impl calls this with MAX_DESERIALIZE_BYTES.
Use this method directly when you need a tighter or looser ceiling.
The intermediate buffer is kept inside a Zeroizing wrapper until after the Box
allocation completes, guaranteeing zeroization even on OOM panic. Oversized buffers
are also zeroized before the error is returned.
Important: this limit is enforced after the upstream deserializer has fully materialized the payload. It is a result-length acceptance bound, not a pre-allocation DoS guard. For untrusted input, enforce size limits at the transport or parser layer upstream.
Trait Implementations§
Source§impl<T: Zeroize + CloneableSecret> Clone for Dynamic<T>
Available on crate feature cloneable only.
impl<T: Zeroize + CloneableSecret> Clone for Dynamic<T>
cloneable only.Source§impl<T> ConstantTimeEq for Dynamic<T>
Available on crate feature ct-eq only.
impl<T> ConstantTimeEq for Dynamic<T>
ct-eq only.Source§impl<'de> Deserialize<'de> for Dynamic<String>
Available on crate feature serde-deserialize only.
impl<'de> Deserialize<'de> for Dynamic<String>
serde-deserialize only.Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for Dynamic<Vec<u8>>
Available on crate feature serde-deserialize only.
impl<'de> Deserialize<'de> for Dynamic<Vec<u8>>
serde-deserialize only.Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl ExposeSecret<String> for Dynamic<String>
impl ExposeSecret<String> for Dynamic<String>
Source§fn expose_secret(&self) -> &String
fn expose_secret(&self) -> &String
Source§impl<T: Zeroize> ExposeSecret<Vec<T>> for Dynamic<Vec<T>>
impl<T: Zeroize> ExposeSecret<Vec<T>> for Dynamic<Vec<T>>
Source§fn expose_secret(&self) -> &Vec<T>
fn expose_secret(&self) -> &Vec<T>
Source§impl ExposeSecretMut<String> for Dynamic<String>
impl ExposeSecretMut<String> for Dynamic<String>
Source§fn expose_secret_mut(&mut self) -> &mut String
fn expose_secret_mut(&mut self) -> &mut String
Source§impl<T: Zeroize> ExposeSecretMut<Vec<T>> for Dynamic<Vec<T>>
impl<T: Zeroize> ExposeSecretMut<Vec<T>> for Dynamic<Vec<T>>
Source§fn expose_secret_mut(&mut self) -> &mut Vec<T>
fn expose_secret_mut(&mut self) -> &mut Vec<T>
Source§impl From<Dynamic<String>> for SecretBox<String>
Converts a Dynamic<String> back into a SecretBox<String>.
impl From<Dynamic<String>> for SecretBox<String>
Converts a Dynamic<String> back into a SecretBox<String>.
Clones the inner String. Both the source and the new wrapper are zeroized on drop.
Source§impl From<Dynamic<String>> for SecretString
Converts a Dynamic<String> into a SecretString (= SecretBox<str>).
impl From<Dynamic<String>> for SecretString
Converts a Dynamic<String> into a SecretString (= SecretBox<str>).
Clones the inner string. Both ends are zeroized on drop.
Source§impl<S: Clone + Zeroize + 'static> From<Dynamic<Vec<S>>> for SecretBox<Vec<S>>
Converts a Dynamic<Vec<S>> back into a SecretBox<Vec<S>>.
impl<S: Clone + Zeroize + 'static> From<Dynamic<Vec<S>>> for SecretBox<Vec<S>>
Converts a Dynamic<Vec<S>> back into a SecretBox<Vec<S>>.
Clones the inner Vec. Both ends are zeroized on drop.
Source§impl<T: Clone + Zeroize + 'static> From<Dynamic<Vec<T>>> for Secret<Vec<T>>
Converts a Dynamic<Vec<T>> into Secret<Vec<T>>.
impl<T: Clone + Zeroize + 'static> From<Dynamic<Vec<T>>> for Secret<Vec<T>>
Converts a Dynamic<Vec<T>> into Secret<Vec<T>>.
Source§impl<T: Clone + Zeroize + 'static> From<Secret<Vec<T>>> for Dynamic<Vec<T>>
Converts Secret<Vec<T>> into a Dynamic<Vec<T>>.
impl<T: Clone + Zeroize + 'static> From<Secret<Vec<T>>> for Dynamic<Vec<T>>
Converts Secret<Vec<T>> into a Dynamic<Vec<T>>.
Source§impl<S: Clone + Zeroize + 'static> From<SecretBox<S>> for Dynamic<S>
Converts a SecretBox<S> into a Dynamic<S> (primary migration path).
impl<S: Clone + Zeroize + 'static> From<SecretBox<S>> for Dynamic<S>
Converts a SecretBox<S> into a Dynamic<S> (primary migration path).
Requires S: Clone because the inner Box<S> cannot be moved out of SecretBox
without unsafe code (SecretBox has a Drop impl). The clone is immediately
wrapped in Dynamic and the original is zeroized on drop.
For zero-copy migration, construct Dynamic<S> directly instead.
Source§impl From<SecretBox<str>> for Dynamic<String>
Converts a SecretString (= SecretBox<str>) into a Dynamic<String>.
impl From<SecretBox<str>> for Dynamic<String>
Converts a SecretString (= SecretBox<str>) into a Dynamic<String>.
Clones the inner str into a new String. Both ends are zeroized on drop.
Source§fn from(sb: SecretString) -> Self
fn from(sb: SecretString) -> Self
Source§impl RevealSecret for Dynamic<String>
impl RevealSecret for Dynamic<String>
Source§fn into_inner(self) -> InnerSecret<String>
fn into_inner(self) -> InnerSecret<String>
Consumes self and returns the inner String wrapped in crate::InnerSecret.
Allocation note: allocates one small Box<String> sentinel (24 bytes on
64-bit) before the swap. If that allocation panics (OOM), self.inner is
unchanged and Dynamic::drop zeroizes the real secret during unwind —
confidentiality is preserved. This is the same OOM-safety pattern used by
from_protected_bytes and deserialize_with_limit.
See RevealSecret::into_inner for full documentation including the
redacted Debug behavior.
Source§fn with_secret<F, R>(&self, f: F) -> R
fn with_secret<F, R>(&self, f: F) -> R
Source§fn expose_secret(&self) -> &String
fn expose_secret(&self) -> &String
Source§impl<T: Zeroize> RevealSecret for Dynamic<Vec<T>>
impl<T: Zeroize> RevealSecret for Dynamic<Vec<T>>
Source§fn into_inner(self) -> InnerSecret<Vec<T>>
fn into_inner(self) -> InnerSecret<Vec<T>>
Consumes self and returns the inner Vec<T> wrapped in crate::InnerSecret.
Allocation note: allocates one small Box<Vec<T>> sentinel (24 bytes on
64-bit) before the swap. If that allocation panics (OOM), self.inner is
unchanged and Dynamic::drop zeroizes the real secret during unwind —
confidentiality is preserved. This is the same OOM-safety pattern used by
from_protected_bytes and deserialize_with_limit.
See RevealSecret::into_inner for full documentation including the
redacted Debug behavior.
Source§fn with_secret<F, R>(&self, f: F) -> R
fn with_secret<F, R>(&self, f: F) -> R
Source§fn expose_secret(&self) -> &Vec<T>
fn expose_secret(&self) -> &Vec<T>
Source§impl RevealSecretMut for Dynamic<String>
impl RevealSecretMut for Dynamic<String>
Source§impl<T: Zeroize + SerializableSecret> Serialize for Dynamic<T>
Available on crate feature serde-serialize only.
impl<T: Zeroize + SerializableSecret> Serialize for Dynamic<T>
serde-serialize only.