From 6a28b6ac1d7f96a7c0879ea36c906590e1edd322 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 17 Sep 2024 12:58:47 -0600 Subject: [PATCH] secrecy: add `SecretString` replacement; ?Sized bounds Adds a type alias for `SecretBox` 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` is valid. --- secrecy/src/lib.rs | 53 +++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/secrecy/src/lib.rs b/secrecy/src/lib.rs index ec351d8d..fef8f404 100644 --- a/secrecy/src/lib.rs +++ b/secrecy/src/lib.rs @@ -36,7 +36,7 @@ extern crate alloc; -use alloc::boxed::Box; +use alloc::{boxed::Box, string::String}; use core::{ any, fmt::{self, Debug}, @@ -55,31 +55,31 @@ pub use zeroize; /// /// Access to the secret inner value occurs through the [`ExposeSecret`] /// or [`ExposeSecretMut`] traits, which provide methods for accessing the inner secret value. -pub struct SecretBox { +pub struct SecretBox { inner_secret: Box, } -impl Zeroize for SecretBox { +impl Zeroize for SecretBox { fn zeroize(&mut self) { self.inner_secret.as_mut().zeroize() } } -impl Drop for SecretBox { +impl Drop for SecretBox { fn drop(&mut self) { self.zeroize() } } -impl ZeroizeOnDrop for SecretBox {} +impl ZeroizeOnDrop for SecretBox {} -impl From> for SecretBox { +impl From> for SecretBox { fn from(source: Box) -> Self { Self::new(source) } } -impl SecretBox { +impl SecretBox { /// Create a secret value using a pre-boxed value. pub fn new(boxed_secret: Box) -> Self { Self { @@ -88,24 +88,24 @@ impl SecretBox { } } -impl SecretBox { - /// Create a secret value using a function that can initialize the vale in-place. - pub fn new_with_mut(ctr: impl FnOnce(&mut S)) -> Self { +impl SecretBox { + /// Create a secret value using a function that can initialize the value in-place. + pub fn init_with_mut(ctr: impl FnOnce(&mut S)) -> Self { let mut secret = Self::default(); ctr(secret.expose_secret_mut()); secret } } -impl SecretBox { +impl SecretBox { /// Create a secret value using the provided function as a constructor. /// /// The implementation makes an effort to zeroize the locally constructed value /// before it is copied to the heap, and constructing it inside the closure minimizes /// the possibility of it being accidentally copied by other code. /// - /// **Note:** using [`Self::new`] or [`Self::new_with_mut`] is preferable when possible, - /// since this method's safety relies on empyric evidence and may be violated on some targets. + /// **Note:** using [`Self::new`] or [`Self::init_with_mut`] is preferable when possible, + /// since this method's safety relies on empiric evidence and may be violated on some targets. pub fn init_with(ctr: impl FnOnce() -> S) -> Self { let mut data = ctr(); let secret = Self { @@ -118,7 +118,7 @@ impl SecretBox { /// Same as [`Self::init_with`], but the constructor can be fallible. /// /// - /// **Note:** using [`Self::new`] or [`Self::new_with_mut`] is preferable when possible, + /// **Note:** using [`Self::new`] or [`Self::init_with_mut`] is preferable when possible, /// since this method's safety relies on empyric evidence and may be violated on some targets. pub fn try_init_with(ctr: impl FnOnce() -> Result) -> Result { let mut data = ctr()?; @@ -130,7 +130,7 @@ impl SecretBox { } } -impl Default for SecretBox { +impl Default for SecretBox { fn default() -> Self { Self { inner_secret: Box::::default(), @@ -138,7 +138,7 @@ impl Default for SecretBox { } } -impl Debug for SecretBox { +impl Debug for SecretBox { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "SecretBox<{}>([REDACTED])", any::type_name::()) } @@ -155,29 +155,42 @@ where } } -impl ExposeSecret for SecretBox { +impl ExposeSecret for SecretBox { fn expose_secret(&self) -> &S { self.inner_secret.as_ref() } } -impl ExposeSecretMut for SecretBox { +impl ExposeSecretMut for SecretBox { fn expose_secret_mut(&mut self) -> &mut S { self.inner_secret.as_mut() } } +/// Secret string type. +/// +/// This is a type alias for [`SecretBox`] which supports some helpful trait impls. +/// +/// Notably it has a [`From`] impl which is the preferred method for construction. +pub type SecretString = SecretBox; + +impl From for SecretString { + fn from(s: String) -> Self { + Self::from(s.into_boxed_str()) + } +} + /// Marker trait for secrets which are allowed to be cloned pub trait CloneableSecret: Clone + Zeroize {} /// Expose a reference to an inner secret -pub trait ExposeSecret { +pub trait ExposeSecret { /// Expose secret: this is the only method providing access to a secret. fn expose_secret(&self) -> &S; } /// Expose a mutable reference to an inner secret -pub trait ExposeSecretMut { +pub trait ExposeSecretMut { /// Expose secret: this is the only method providing access to a secret. fn expose_secret_mut(&mut self) -> &mut S; }