secure-gate
no_std-compatible wrappers for sensitive data with explicit exposure requirements.
🔒 Note: This crate is in active development and has not undergone independent security audit. Please review it for your use case and handle sensitive data with care. See SECURITY.md for detailed security considerations.
Fixed<T>— Stack-allocated wrapperDynamic<T>— Heap-allocated wrapperFixedRandom<N>— Stack-allocated cryptographically secure random bytesDynamicRandom— Heap-allocated cryptographically secure random bytesCloneableArray<const N: usize>— Cloneable fixed-size stack secret ([u8; N])CloneableString— Cloneable heap-allocated text secret (String)CloneableVec— Cloneable heap-allocated binary secret (Vec<u8])HexString— Validated lowercase hexadecimal string wrapperBase64String— Validated URL-safe base64 string wrapper (no padding)Bech32String— Validated Bech32/Bech32m string wrapper
Memory containing secrets is zeroed on drop, including spare capacity where applicable (when zeroize is enabled).
Access requires an explicit .expose_secret() (or .expose_secret_mut()) call — no Deref or implicit paths.
Installation
[]
= "0.7.0-rc.7"
Basic configuration includes zeroize and ct-eq (via the secure meta-feature) for secure memory handling and constant-time equality.
Recommended for most users (secure defaults):
= "0.7.0-rc.7" # default enables "secure"
Batteries-included (all optional features):
= { = "0.7.0-rc.7", = ["full"] }
Constrained/minimal builds (no zeroization or ct-eq — strongly discouraged for production):
= { = "0.7.0-rc.7", = false, = ["insecure"] }
Features
| Feature | Description |
|---|---|
secure (default) |
Enables zeroize + ct-eq — secure memory wiping and constant-time equality (recommended) |
zeroize |
Memory zeroing on drop + opt-in safe cloning (requires zeroize crate) |
ct-eq |
Constant-time equality checks to prevent timing attacks (requires subtle crate) |
rand |
Random generation (FixedRandom<N>::generate(), DynamicRandom::generate()) |
encoding |
All encoding support (encoding-hex, encoding-base64, encoding-bech32) |
encoding-hex |
Hex encoding + HexString + random hex methods |
encoding-base64 |
Base64String (URL-safe, no padding) |
encoding-bech32 |
Bech32String (Bech32/Bech32m, mixed-case input, lowercase storage) |
full |
Meta-feature enabling all optional features (includes secure) |
insecure |
Explicit opt-out for no-default-features builds (disables zeroize and ct-eq) — not recommended for production |
no_std + alloc compatible. Features add no overhead when unused.
Security Model & Design Philosophy
secure-gate prioritizes auditability and explicitness over implicit convenience.
All secret access requires an explicit .expose_secret() (or .expose_secret_mut()) call — making exposures grep-able and preventing hidden leaks.
These calls are zero-cost #[inline(always)] reborrows (fully elided by the optimizer). The explicitness is deliberate "theater" for humans and auditors, with no runtime overhead.
Quick Start
use ;
// Recommended: semantic aliases for clarity
fixed_alias!; // Fixed-size byte secret
dynamic_alias!; // Heap string secret
// Create secrets
let key: Aes256Key = .into; // From array/slice
let mut pw: Password = "hunter2".into; // From &str or String
// Access (zero-cost)
assert_eq!;
let key_bytes = key.expose_secret; // &[u8; 32]
// Mutable access
pw.expose_secret_mut.push;
// See dedicated sections below for:
// - Opt-In Safe Cloning (`zeroize` feature)
// - Random Generation (`rand` feature)
// - Encoding (`encoding-*` features)
// - Constant-Time Equality (`ct-eq` feature)
Opt-In Safe Cloning
Cloning secret data is opt-in and only available when the zeroize feature is enabled.
This ensures cloning is deliberate, auditable, and always paired with secure zeroization.
Key mechanism: The CloneSafe marker trait.
To enable safe cloning:
- Implement or derive
Clone - Implement or derive
Zeroize - Implement
CloneSafe(blanket implementations exist for primitives and fixed arrays)
This prevents accidental deep copies that could bypass zeroization.
Pre-Built Cloneable Types
| Type | Allocation | Inner Data | Typical Use Case |
|---|---|---|---|
CloneableArray<const N: usize> |
Stack | [u8; N] |
Fixed-size keys, nonces |
CloneableString |
Heap | String |
Passwords, tokens, API keys |
CloneableVec |
Heap | Vec<u8> |
Variable-length binary secrets |
use ;
Recommended: Semantic Aliases
use ;
Minimizing Stack Exposure
Use init_with / try_init_with when reading from untrusted sources:
use CloneableString;
Custom Cloneable Types
Note: Custom implementations of CloneSafe are possible but discouraged — stick to the pre-baked CloneableArray, CloneableString, or CloneableVec types unless you have a strong justification. Improper impls can undermine the crate's cloning guarantees.
use CloneSafe;
Random Generation
FixedRandom<N> can only be constructed via a cryptographically secure RNG.
Direct generation is also available:
Encoding
Encoding requires explicit .expose_secret(). Invalid inputs to .new() are zeroed when zeroize is enabled.
Constant-Time Equality
Available on Fixed<[u8; N]> and Dynamic<T> where T: AsRef<[u8]>.
Macros
All macros require explicit visibility (e.g., pub, pub(crate), or none for private).
Basic Aliases
use ;
fixed_alias!; // Fixed<[u8; 32]>
dynamic_alias!; // Dynamic<String>
Generic Aliases
For reusable or library-provided secret types:
use ;
fixed_generic_alias!;
dynamic_generic_alias!; // Vec<u8> can be any type
Custom doc strings (optional):
use ;
fixed_generic_alias!;
dynamic_generic_alias!;
Random-Only Fixed Aliases (rand feature)
These macros create type aliases to Fixed<[u8; N]>, Dynamic<T>, FixedRandom<N>, or their generic counterparts, inheriting all methods and security guarantees.
Memory Guarantees (zeroize enabled)
| Type | Allocation | Auto-zero | Full wipe | Slack eliminated | Notes |
|---|---|---|---|---|---|
Fixed<T> |
Stack | Yes | Yes | Yes (no heap) | |
Dynamic<T> |
Heap | Yes | Yes | No (until drop) | Use shrink_to_fit() |
FixedRandom<N> |
Stack | Yes | Yes | Yes | |
DynamicRandom |
Heap | Yes | Yes | No (until drop) | |
HexString |
Heap | Yes (invalid input) | Yes | No (until drop) | Validated hex |
Base64String |
Heap | Yes (invalid input) | Yes | No (until drop) | Validated base64 |
Bech32String |
Heap | Yes (invalid input) | Yes | No (until drop) | Validated Bech32/Bech32m |
| For in-depth security analysis, see SECURITY.md. |
Performance
The wrappers add no runtime overhead compared to raw types in benchmarks.
Security Checklist
To maximize the security of your application when using secure-gate, adhere to these guidelines:
- Use secure defaults: Rely on the default feature set (
secure) for automatic memory wiping (zeroize) and constant-time equality (ct-eq). Avoid--no-default-featuresunless you have a strong reason (e.g., constrained embedded environments). - Pre-validate encoding inputs: For Bech32 and other encodings, validate inputs (e.g., HRPs) upfront. Use
try_*methods (e.g.,try_to_bech32) and handle errors properly to avoid issues from malformed data. - Prefer constant-time comparisons: Use
.ct_eq()for all sensitive equality checks to prevent timing attacks. - Minimize secret exposures: Audit your code for
.expose_secret()calls; keep them minimal, logged, and justified. Avoid unnecessary or prolonged exposures. - Restrict cloning: Only clone when necessary. Prefer built-in
Cloneable*types; be cautious with customCloneSafeimplementations. - Conservative feature usage: Enable only the features you need (e.g., specific encodings) to reduce attack surface.
- Regular review: Periodically audit your secret handling logic, especially after dependency updates.
- Security considerations: Refer to SECURITY.md for detailed security considerations.
Changelog
License
MIT OR Apache-2.0