Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ console = "0.16.0"
indicatif = "0.18.0"
tabled = "0.20.0"
colored = "3.0.0"
zeroize = "1.7.0"

[dev-dependencies]
tempfile = "3.20.0"
Expand Down
7 changes: 4 additions & 3 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::error::ConversionError;

Check warning on line 1 in src/cli/mod.rs

View workflow job for this annotation

GitHub Actions / Test Suite (ubuntu-latest, stable)

Diff in /home/runner/work/forge/forge/src/cli/mod.rs

Check warning on line 1 in src/cli/mod.rs

View workflow job for this annotation

GitHub Actions / Test Suite (ubuntu-latest, stable)

Diff in /home/runner/work/forge/forge/src/cli/mod.rs
use clap::Parser;
use crate::secure::SecurePassword;
use std::path::Path;

#[derive(Parser, Debug)]
Expand Down Expand Up @@ -53,9 +54,9 @@
}

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.as_deref())
}

/// Get the output directory, defaulting to current directory
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
1 change: 1 addition & 0 deletions src/openssl/parser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::error::ConversionError;
use crate::openssl::ParsedPfx;
use crate::secure::SecurePassword;

Check failure on line 3 in src/openssl/parser.rs

View workflow job for this annotation

GitHub Actions / Minimum Supported Rust Version

unused import: `crate::secure::SecurePassword`

Check failure on line 3 in src/openssl/parser.rs

View workflow job for this annotation

GitHub Actions / Test Suite (macos-latest, stable)

unused import: `crate::secure::SecurePassword`
use openssl::pkcs12::Pkcs12;
use std::ffi::OsStr;
use std::fs;
Expand Down
58 changes: 58 additions & 0 deletions src/secure.rs
Original file line number Diff line number Diff line change
@@ -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)]
pub struct SecurePassword {
value: String,
}

impl SecurePassword {
/// Create a new secure password from a string
pub fn new<S: AsRef<str>>(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<S: AsRef<str>>(value: Option<S>) -> Self {
match value {
Some(s) => Self::new(s),
None => Self::new(""),

Check warning on line 24 in src/secure.rs

View workflow job for this annotation

GitHub Actions / Test Suite (ubuntu-latest, stable)

Diff in /home/runner/work/forge/forge/src/secure.rs
}
}

/// 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]")

Check warning on line 56 in src/secure.rs

View workflow job for this annotation

GitHub Actions / Test Suite (ubuntu-latest, stable)

Diff in /home/runner/work/forge/forge/src/secure.rs
}
}
Loading