Skip to content

Commit 23d134d

Browse files
secrecy: add SecretString replacement; ?Sized bounds (#1213)
Adds a type alias for `SecretBox<str>` to replace the previous `SecretString` type and provide a better migration path. To support this, we need to add `?Sized` bounds to `SecretBox` so `SecretBox<str>` is valid.
1 parent 14c867a commit 23d134d

File tree

1 file changed

+33
-20
lines changed

1 file changed

+33
-20
lines changed

secrecy/src/lib.rs

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
extern crate alloc;
3838

39-
use alloc::boxed::Box;
39+
use alloc::{boxed::Box, string::String};
4040
use core::{
4141
any,
4242
fmt::{self, Debug},
@@ -55,31 +55,31 @@ pub use zeroize;
5555
///
5656
/// Access to the secret inner value occurs through the [`ExposeSecret`]
5757
/// or [`ExposeSecretMut`] traits, which provide methods for accessing the inner secret value.
58-
pub struct SecretBox<S: Zeroize> {
58+
pub struct SecretBox<S: Zeroize + ?Sized> {
5959
inner_secret: Box<S>,
6060
}
6161

62-
impl<S: Zeroize> Zeroize for SecretBox<S> {
62+
impl<S: Zeroize + ?Sized> Zeroize for SecretBox<S> {
6363
fn zeroize(&mut self) {
6464
self.inner_secret.as_mut().zeroize()
6565
}
6666
}
6767

68-
impl<S: Zeroize> Drop for SecretBox<S> {
68+
impl<S: Zeroize + ?Sized> Drop for SecretBox<S> {
6969
fn drop(&mut self) {
7070
self.zeroize()
7171
}
7272
}
7373

74-
impl<S: Zeroize> ZeroizeOnDrop for SecretBox<S> {}
74+
impl<S: Zeroize + ?Sized> ZeroizeOnDrop for SecretBox<S> {}
7575

76-
impl<S: Zeroize> From<Box<S>> for SecretBox<S> {
76+
impl<S: Zeroize + ?Sized> From<Box<S>> for SecretBox<S> {
7777
fn from(source: Box<S>) -> Self {
7878
Self::new(source)
7979
}
8080
}
8181

82-
impl<S: Zeroize> SecretBox<S> {
82+
impl<S: Zeroize + ?Sized> SecretBox<S> {
8383
/// Create a secret value using a pre-boxed value.
8484
pub fn new(boxed_secret: Box<S>) -> Self {
8585
Self {
@@ -88,24 +88,24 @@ impl<S: Zeroize> SecretBox<S> {
8888
}
8989
}
9090

91-
impl<S: Zeroize + Default> SecretBox<S> {
92-
/// Create a secret value using a function that can initialize the vale in-place.
93-
pub fn new_with_mut(ctr: impl FnOnce(&mut S)) -> Self {
91+
impl<S: Zeroize + Default + ?Sized> SecretBox<S> {
92+
/// Create a secret value using a function that can initialize the value in-place.
93+
pub fn init_with_mut(ctr: impl FnOnce(&mut S)) -> Self {
9494
let mut secret = Self::default();
9595
ctr(secret.expose_secret_mut());
9696
secret
9797
}
9898
}
9999

100-
impl<S: Zeroize + Clone> SecretBox<S> {
100+
impl<S: Zeroize + Clone + ?Sized> SecretBox<S> {
101101
/// Create a secret value using the provided function as a constructor.
102102
///
103103
/// The implementation makes an effort to zeroize the locally constructed value
104104
/// before it is copied to the heap, and constructing it inside the closure minimizes
105105
/// the possibility of it being accidentally copied by other code.
106106
///
107-
/// **Note:** using [`Self::new`] or [`Self::new_with_mut`] is preferable when possible,
108-
/// since this method's safety relies on empyric evidence and may be violated on some targets.
107+
/// **Note:** using [`Self::new`] or [`Self::init_with_mut`] is preferable when possible,
108+
/// since this method's safety relies on empiric evidence and may be violated on some targets.
109109
pub fn init_with(ctr: impl FnOnce() -> S) -> Self {
110110
let mut data = ctr();
111111
let secret = Self {
@@ -118,7 +118,7 @@ impl<S: Zeroize + Clone> SecretBox<S> {
118118
/// Same as [`Self::init_with`], but the constructor can be fallible.
119119
///
120120
///
121-
/// **Note:** using [`Self::new`] or [`Self::new_with_mut`] is preferable when possible,
121+
/// **Note:** using [`Self::new`] or [`Self::init_with_mut`] is preferable when possible,
122122
/// since this method's safety relies on empyric evidence and may be violated on some targets.
123123
pub fn try_init_with<E>(ctr: impl FnOnce() -> Result<S, E>) -> Result<Self, E> {
124124
let mut data = ctr()?;
@@ -130,15 +130,15 @@ impl<S: Zeroize + Clone> SecretBox<S> {
130130
}
131131
}
132132

133-
impl<S: Zeroize + Default> Default for SecretBox<S> {
133+
impl<S: Zeroize + ?Sized + Default> Default for SecretBox<S> {
134134
fn default() -> Self {
135135
Self {
136136
inner_secret: Box::<S>::default(),
137137
}
138138
}
139139
}
140140

141-
impl<S: Zeroize> Debug for SecretBox<S> {
141+
impl<S: Zeroize + ?Sized> Debug for SecretBox<S> {
142142
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143143
write!(f, "SecretBox<{}>([REDACTED])", any::type_name::<S>())
144144
}
@@ -155,29 +155,42 @@ where
155155
}
156156
}
157157

158-
impl<S: Zeroize> ExposeSecret<S> for SecretBox<S> {
158+
impl<S: Zeroize + ?Sized> ExposeSecret<S> for SecretBox<S> {
159159
fn expose_secret(&self) -> &S {
160160
self.inner_secret.as_ref()
161161
}
162162
}
163163

164-
impl<S: Zeroize> ExposeSecretMut<S> for SecretBox<S> {
164+
impl<S: Zeroize + ?Sized> ExposeSecretMut<S> for SecretBox<S> {
165165
fn expose_secret_mut(&mut self) -> &mut S {
166166
self.inner_secret.as_mut()
167167
}
168168
}
169169

170+
/// Secret string type.
171+
///
172+
/// This is a type alias for [`SecretBox<str>`] which supports some helpful trait impls.
173+
///
174+
/// Notably it has a [`From<String>`] impl which is the preferred method for construction.
175+
pub type SecretString = SecretBox<str>;
176+
177+
impl From<String> for SecretString {
178+
fn from(s: String) -> Self {
179+
Self::from(s.into_boxed_str())
180+
}
181+
}
182+
170183
/// Marker trait for secrets which are allowed to be cloned
171184
pub trait CloneableSecret: Clone + Zeroize {}
172185

173186
/// Expose a reference to an inner secret
174-
pub trait ExposeSecret<S> {
187+
pub trait ExposeSecret<S: ?Sized> {
175188
/// Expose secret: this is the only method providing access to a secret.
176189
fn expose_secret(&self) -> &S;
177190
}
178191

179192
/// Expose a mutable reference to an inner secret
180-
pub trait ExposeSecretMut<S> {
193+
pub trait ExposeSecretMut<S: ?Sized> {
181194
/// Expose secret: this is the only method providing access to a secret.
182195
fn expose_secret_mut(&mut self) -> &mut S;
183196
}

0 commit comments

Comments
 (0)