secure_gate/lib.rs
1// #![doc = include_str!("../README.md")] //uncomment for doctest runs
2
3// Forbid unsafe code unconditionally
4#![forbid(unsafe_code)]
5
6//! secure-gate — Secure secret wrappers with explicit access & automatic zeroization
7//!
8//! Secrets are **automatically zeroized on drop** (the inner type must implement [`Zeroize`](zeroize::Zeroize)).
9//! Explicit access only via [`RevealSecret`]/[`RevealSecretMut`] — no `Deref`, no accidental leaks.
10//! `Debug` always prints `[REDACTED]`.
11//!
12//! - [`Fixed<T>`] — stack-allocated, compile-time-sized secrets (keys, nonces, tokens)
13//! - [`Dynamic<T>`] — heap-allocated, variable-length secrets (passwords, API keys, ciphertexts)
14//!
15//! # Feature flags
16//!
17//! - `alloc` *(default)*: Heap-allocated [`Dynamic<T>`] + full zeroization of spare capacity
18//! - `std`: Full `std` support (implies `alloc`)
19//! - `ct-eq`: [`ConstantTimeEq`] constant-time equality (`subtle`)
20//! - `rand`: Secure random generation via `OsRng`; `no_std` compatible for `Fixed<T>` (no heap required)
21//! - `cloneable`: [`CloneableSecret`] opt-in cloning
22//! - `serde-serialize` / `serde-deserialize`: Serde support
23//! - `encoding-hex` / `encoding-base64` / `encoding-bech32` / `encoding-bech32m`: Per-format encoding
24//! - `full`: All features
25//!
26//! # no_std
27//!
28//! `no_std` compatible. [`Fixed<T>`] works without `alloc`. Enable `alloc` (default) for
29//! [`Dynamic<T>`]. For pure stack / embedded builds, use `default-features = false`.
30//!
31//! See the [README](https://github.com/Slurp9187/secure-gate/blob/main/README.md) and
32//! [SECURITY.md](https://github.com/Slurp9187/secure-gate/blob/main/SECURITY.md) for full details.
33
34#[cfg(feature = "alloc")]
35extern crate alloc;
36
37#[cfg(feature = "alloc")]
38mod dynamic;
39
40/// Fixed-size secret wrapper types - always available with zero dependencies.
41/// These provide fundamental secure storage abstractions for fixed-size data.
42mod fixed;
43
44/// Centralized error types - always available.
45mod error;
46
47/// Core traits for wrapper polymorphism - always available.
48pub mod traits;
49
50#[cfg(feature = "alloc")]
51/// Heap-allocated secret wrapper with explicit access and automatic zeroization on drop.
52///
53/// Requires `alloc` feature. Inner type must implement `Zeroize`.
54pub use dynamic::Dynamic;
55
56#[cfg(all(feature = "alloc", feature = "serde-deserialize"))]
57/// Default maximum byte length for `Dynamic<Vec<u8>>` / `Dynamic<String>` deserialization (1 MiB).
58///
59/// The standard `serde::Deserialize` impl for both types rejects payloads exceeding this value.
60/// Pass a custom ceiling to [`Dynamic::deserialize_with_limit`] when a different limit is needed.
61///
62/// **Important:** this limit is enforced *after* the upstream deserializer has fully
63/// materialized the payload. It is a **result-length acceptance bound**, not a
64/// pre-allocation DoS guard. For untrusted input, enforce size limits at the
65/// transport or parser layer upstream.
66pub use dynamic::MAX_DESERIALIZE_BYTES;
67
68/// Stack-allocated secret wrapper with explicit access and automatic zeroization on drop.
69///
70/// Always available. Inner type must implement `Zeroize`.
71pub use fixed::Fixed;
72
73#[cfg(feature = "cloneable")]
74/// Marker trait for secrets that can be cloned.
75///
76/// Enables cloning of wrapped secrets. Requires `cloneable` feature.
77pub use traits::CloneableSecret;
78
79#[cfg(feature = "ct-eq")]
80/// Constant-time equality for secrets.
81///
82/// Provides `ct_eq()` method using `subtle`. Requires `ct-eq` feature.
83pub use traits::ConstantTimeEq;
84
85/// Explicit immutable access to secret contents.
86///
87/// Provides `expose_secret()` and `with_secret()` methods.
88pub use traits::RevealSecret;
89
90/// Explicit mutable access to secret contents.
91///
92/// Provides `expose_secret_mut()` and `with_secret_mut()` methods.
93pub use traits::RevealSecretMut;
94
95#[cfg(feature = "serde-serialize")]
96/// Marker trait for secrets that can be serialized with Serde.
97///
98/// Enables serialization. Requires `serde-serialize` feature.
99pub use traits::SerializableSecret;
100
101// Type alias macros (always available)
102mod macros;
103
104#[cfg(feature = "encoding-base64")]
105pub use traits::FromBase64UrlStr;
106
107#[cfg(feature = "encoding-bech32")]
108pub use traits::FromBech32Str;
109
110#[cfg(feature = "encoding-bech32m")]
111pub use traits::FromBech32mStr;
112
113#[cfg(feature = "encoding-hex")]
114pub use traits::FromHexStr;
115
116#[cfg(feature = "encoding-base64")]
117pub use traits::ToBase64Url;
118
119#[cfg(feature = "encoding-bech32")]
120pub use traits::ToBech32;
121
122#[cfg(feature = "encoding-bech32m")]
123pub use traits::ToBech32m;
124
125#[cfg(feature = "encoding-hex")]
126pub use traits::ToHex;
127
128#[cfg(any(
129 feature = "encoding-hex",
130 feature = "encoding-base64",
131 feature = "encoding-bech32",
132 feature = "encoding-bech32m",
133))]
134pub use traits::SecureDecoding;
135
136#[cfg(any(
137 feature = "encoding-hex",
138 feature = "encoding-base64",
139 feature = "encoding-bech32",
140 feature = "encoding-bech32m",
141))]
142pub use traits::SecureEncoding;
143
144#[cfg(any(feature = "encoding-bech32", feature = "encoding-bech32m"))]
145pub use error::Bech32Error;
146
147#[cfg(feature = "encoding-base64")]
148pub use error::Base64Error;
149
150#[cfg(feature = "encoding-hex")]
151pub use error::HexError;
152
153pub use error::DecodingError;
154pub use error::FromSliceError;