Expand description
Simple lightweight secret wrappers that zeroize on drop
and prevent accidental logging. Built on RustCrypto zeroize
This crate provides three owned wrappers around in-memory secret material,
backed by the RustCrypto zeroize crate:
SecretStringowns a heapString(e.g. NKEY seeds,.credstext, invite/recovery codes, base64-encoded credentials).SecretBytesowns a heapVec<u8>(e.g. decrypted plaintext buffers, credential blobs, message bodies that may contain secrets).SecretArray<N>owns a fixed-size stack[u8; N](e.g. X25519 private seeds, AEAD keys, shared secrets — typically[u8; 32]).
§Guarantees
Every wrapper:
- Zeroizes its backing storage on
Drop(heap allocation contents for the string/bytes wrappers, the stack bytes forSecretArray). - Redacts
Debug.Displayis not implemented to prevent{}formatting. Secret contents or length are not printed. - Produces an independently owned value on
Clone— a deep copy with its own allocation (for the heap types) whose ownDropalso zeroizes. This holds for clones moved into async blocks/tasks.
§Ownership contract
- Borrow in: callers wrap only when this code takes ownership of a
secret. Code that merely reads a secret should accept
&str/&[u8]. - Wrap on ownership: construct via
newor theFromimpls when an owned secret enters the crate that owns it. - Borrow for use: read through
expose_secret(returns&str/&[u8]); the borrow never escapes the wrapper. - Plain owned out: when ownership must leave the library, use the
#[must_use]extractors (into_string,into_vec,into_inner). These return the plain owned value and intentionally do not zeroize the moved-out value — the caller then owns leak prevention. Their inputs are consumed, so no wrapped copy lingers.
§How to use (recommended policy)
These wrappers are designed to be internal to your crate, used to protect
private owned fields. Keep Secret* types out of your public API:
accept &str / &[u8] in inputs, and return borrowed accessors via expose_secret
for normal use. Use plain owned extractors only when ownership must leave the boundary.
serde::Serialize / Deserialize are intentionally not implemented. If serializing
is needed, it should be in targeted, auditable call-sites.
Structs§
- Secret
Array - An owned, zeroizing wrapper around a fixed-size
[u8; N]stack array. - Secret
Bytes - An owned, zeroizing wrapper around a
Vec<u8>. - Secret
String - An owned, zeroizing wrapper around a
String.