secure_gate/lib.rs
1// uncomment for doctest runs
2// #![doc = include_str!("../EXAMPLES.md")]
3// #![doc = include_str!("../README.md")]
4// Forbid unsafe code unconditionally
5#![forbid(unsafe_code)]
6
7//! Zero-cost secure wrappers for secrets — [`Dynamic<T>`] for heap-allocated variable-length data,
8//! [`Fixed<T>`] for stack-allocated fixed-size data.
9//!
10//! This crate provides explicit, guarded wrappers for sensitive values (e.g. keys, tokens, ciphertexts)
11//! with controlled exposure via `.expose_secret()` / `.expose_secret_mut()`. No accidental leaks via
12//! `Deref`, `AsRef`, or implicit conversions.
13//!
14//! ## Quickstart
15//!
16//! Add this to your `Cargo.toml`:
17//!
18//! ```toml
19//! [dependencies]
20//! secure-gate = "0.7.0-rc.14"
21//! ```
22//!
23//! Here's a basic example with `Fixed` for a stack-allocated secret (no extra features needed):
24//!
25//! ```rust
26//! use secure_gate::Fixed;
27//!
28//! // Wrap a fixed-size secret (e.g., a 32-byte key)
29//! let secret = Fixed::<[u8; 32]>::new([42; 32]);
30//!
31//! // Expose it temporarily for use, zeroizing afterward
32//! let value = secret.expose_secret(|exposed| {
33//! // Do something with `exposed` (e.g., encrypt)
34//! exposed[0]
35//! });
36//! ```
37//!
38//! For dynamic secrets, enable the `alloc` feature and use `Dynamic<T>` similarly.
39//!
40//! Check [README.md](https://github.com/Slurp9187/secure-gate/blob/v0.7.0-rc.14/README.md) for more examples and feature flags.
41//!
42//! ## Equality Options
43//!
44//!
45//! [`ConstantTimeEq`] (via `ct-eq` feature): Direct byte-by-byte constant-time comparison using `subtle`.
46//! Best for small/fixed-size secrets (< ~256–512 bytes) where speed matters most.
47//!
48//! [`ConstantTimeEqExt`] (via `ct-eq-hash` feature): BLAKE3 hash -> constant-time compare on fixed 32-byte digest.
49//! Faster for large/variable secrets (e.g. ML-KEM ciphertexts ~1–1.5 KiB, ML-DSA signatures ~2–4 KiB),
50//! with length hiding and optional keyed mode (`rand` for per-process random key).
51//!
52//! See the ConstantTimeEqExt trait documentation for performance numbers, security properties (probabilistic, timing-safe), and guidance on when to choose each (or hybrid).
53
54// Note: Enabling both 'alloc' and 'no-alloc' allows 'alloc' to take precedence.
55// This is permitted for docs.rs compatibility (--all-features) but should be avoided in normal builds.
56// Prefer using 'no-alloc' alone for true no-heap builds.
57
58#[cfg(feature = "alloc")]
59extern crate alloc;
60
61/// Dynamic secret wrapper types - available with `alloc` feature.
62/// These provide fundamental secure storage abstractions for dynamic data.
63#[cfg(feature = "alloc")]
64mod dynamic;
65
66/// Fixed-size secret wrapper types - always available with zero dependencies.
67/// These provide fundamental secure storage abstractions for fixed-size data.
68mod fixed;
69
70/// Centralized error types - always available.
71mod error;
72
73/// Core traits for wrapper polymorphism - always available.
74mod traits;
75
76#[cfg(feature = "alloc")]
77/// Re-export of the [`Dynamic`] type.
78pub use dynamic::Dynamic;
79/// Re-export of the [`Fixed`] type.
80pub use fixed::Fixed;
81
82#[cfg(feature = "cloneable")]
83pub use traits::CloneableSecret;
84/// Re-export of the traits.
85#[cfg(feature = "ct-eq")]
86pub use traits::ConstantTimeEq;
87#[cfg(feature = "ct-eq-hash")]
88pub use traits::ConstantTimeEqExt;
89#[cfg(feature = "serde-serialize")]
90pub use traits::SerializableSecret;
91pub use traits::{ExposeSecret, ExposeSecretMut};
92
93// Type alias macros (always available).
94// Convenient macros for creating custom secret wrapper types.
95mod macros;
96
97#[cfg(feature = "encoding-base64")]
98pub use traits::FromBase64UrlStr;
99#[cfg(feature = "encoding-bech32")]
100pub use traits::FromBech32Str;
101#[cfg(any(feature = "encoding-bech32", feature = "encoding-bech32m"))]
102pub use traits::FromBech32mStr;
103#[cfg(feature = "encoding-hex")]
104pub use traits::FromHexStr;
105
106#[cfg(feature = "encoding-base64")]
107pub use traits::ToBase64Url;
108#[cfg(feature = "encoding-bech32")]
109pub use traits::ToBech32;
110#[cfg(any(feature = "encoding-bech32", feature = "encoding-bech32m"))]
111pub use traits::ToBech32m;
112#[cfg(feature = "encoding-hex")]
113pub use traits::ToHex;
114
115#[cfg(any(
116 feature = "encoding-hex",
117 feature = "encoding-base64",
118 feature = "encoding-bech32",
119 feature = "encoding-bech32m"
120))]
121pub use traits::{SecureDecoding, SecureEncoding};
122
123/// Re-export of [`Bech32Error`] for convenience when using bech32 encoding/decoding.
124#[cfg(feature = "encoding-bech32")]
125pub use error::Bech32Error;
126
127/// Re-export of [`Base64Error`] for convenience when using base64 decoding.
128#[cfg(feature = "encoding-base64")]
129pub use error::Base64Error;
130
131/// Re-export of [`HexError`] for convenience when using hex decoding.
132#[cfg(feature = "encoding-hex")]
133pub use error::HexError;
134
135/// Re-export of [`DecodingError`] for convenience in decoding operations.
136pub use error::DecodingError;