From 615acc4fd204fcbac1ee1e030aae45a77a209fa5 Mon Sep 17 00:00:00 2001 From: "tembo-io[bot]" <208362400+tembo-io[bot]@users.noreply.github.com> Date: Mon, 9 Jun 2025 15:08:09 +0000 Subject: [PATCH 1/3] feat: Add secure module and update CLI configuration --- Cargo.toml | 1 + src/cli/mod.rs | 7 +++--- src/lib.rs | 2 ++ src/openssl/parser.rs | 1 + src/secure.rs | 58 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 src/secure.rs diff --git a/Cargo.toml b/Cargo.toml index bd76d61..0f682aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ console = "0.15.11" indicatif = "0.17.11" tabled = "0.20.0" colored = "3.0.0" +zeroize = "1.7.0" [dev-dependencies] tempfile = "3.20.0" diff --git a/src/cli/mod.rs b/src/cli/mod.rs index f6f047a..1b87c74 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,4 +1,5 @@ use clap::Parser; +use crate::secure::SecurePassword; #[derive(Parser, Debug)] #[command( @@ -51,9 +52,9 @@ pub struct Args { } impl Args { - /// Get the password, defaulting to empty string if none provided - pub fn password(&self) -> &str { - self.password.as_deref().unwrap_or("") + /// Get the password, wrapped in a secure container that zeroizes memory when dropped + pub fn password(&self) -> SecurePassword { + SecurePassword::from_option(&self.password) } /// Get the output directory, defaulting to current directory diff --git a/src/lib.rs b/src/lib.rs index be8bf13..4e5fe8b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,9 @@ pub mod converter; pub mod error; pub mod openssl; pub mod output; +pub mod secure; // Re-export commonly used types pub use error::ConversionError; pub use openssl::{ParsedPfx, PemFormatter, PfxParser}; +pub use secure::SecurePassword; diff --git a/src/openssl/parser.rs b/src/openssl/parser.rs index 444eee4..8c9284a 100644 --- a/src/openssl/parser.rs +++ b/src/openssl/parser.rs @@ -1,5 +1,6 @@ use crate::error::ConversionError; use crate::openssl::ParsedPfx; +use crate::secure::SecurePassword; use openssl::pkcs12::Pkcs12; use std::fs; use std::path::Path; diff --git a/src/secure.rs b/src/secure.rs new file mode 100644 index 0000000..9494a00 --- /dev/null +++ b/src/secure.rs @@ -0,0 +1,58 @@ +use std::fmt; +use std::ops::Deref; +use zeroize::Zeroize; + +/// A secure password container that automatically zeroizes memory when dropped +#[derive(Clone, Debug)] +pub struct SecurePassword { + value: String, +} + +impl SecurePassword { + /// Create a new secure password from a string + pub fn new>(value: S) -> Self { + Self { + value: value.as_ref().to_string(), + } + } + + /// Create a new secure password from an optional string + /// Returns a secure password with an empty string if None is provided + pub fn from_option>(value: Option) -> Self { + match value { + Some(s) => Self::new(s), + None => Self::new(""), + } + } + + /// Borrow the password as a string slice + pub fn as_str(&self) -> &str { + &self.value + } + + /// Check if the password is empty + pub fn is_empty(&self) -> bool { + self.value.is_empty() + } +} + +impl Deref for SecurePassword { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.value + } +} + +impl Drop for SecurePassword { + fn drop(&mut self) { + self.value.zeroize(); + } +} + +// Prevent accidentally displaying the password in logs or debug output +impl fmt::Display for SecurePassword { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "[REDACTED]") + } +} \ No newline at end of file From dea8e0f3bd1f923177354e58ac04545e9c396745 Mon Sep 17 00:00:00 2001 From: Nick Hudson Date: Tue, 15 Jul 2025 08:21:42 -0500 Subject: [PATCH 2/3] Update src/cli/mod.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/cli/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 8325fdd..869cf79 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -56,7 +56,7 @@ pub struct Args { impl Args { /// Get the password, wrapped in a secure container that zeroizes memory when dropped pub fn password(&self) -> SecurePassword { - SecurePassword::from_option(&self.password) + SecurePassword::from_option(self.password.as_deref()) } /// Get the output directory, defaulting to current directory From 6e2841ef67991aac3796651f4dab44dfa7471bf2 Mon Sep 17 00:00:00 2001 From: Nick Hudson Date: Tue, 15 Jul 2025 08:21:47 -0500 Subject: [PATCH 3/3] Update src/secure.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/secure.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/secure.rs b/src/secure.rs index 9494a00..cde1764 100644 --- a/src/secure.rs +++ b/src/secure.rs @@ -3,7 +3,7 @@ use std::ops::Deref; use zeroize::Zeroize; /// A secure password container that automatically zeroizes memory when dropped -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct SecurePassword { value: String, }