From 2fb22d9ccef65fe35ae258a87339b5f5e9784555 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 6 Sep 2025 14:48:09 -0600 Subject: [PATCH] mcf: rename `PasswordHash`/`PasswordHashRef` Renames the following: - `McfHash` => `PasswordHash` - `McfHashRef` => `PasswordHashRef` This makes it much clearer the types represent password hash strings --- mcf/src/lib.rs | 64 +++++++++++++++++++++++++----------------------- mcf/tests/mcf.rs | 26 ++++++++++---------- 2 files changed, 47 insertions(+), 43 deletions(-) diff --git a/mcf/src/lib.rs b/mcf/src/lib.rs index d06c54116..caded1ad0 100644 --- a/mcf/src/lib.rs +++ b/mcf/src/lib.rs @@ -25,19 +25,20 @@ pub use error::{Error, Result}; pub use fields::{Field, Fields}; #[cfg(feature = "alloc")] -pub use allocating::McfHash; +pub use allocating::PasswordHash; /// Debug message used in panics when invariants aren't properly held. const INVARIANT_MSG: &str = "should be ensured valid by constructor"; -/// Zero-copy decoder for hashes in the Modular Crypt Format (MCF). +/// Password hash reference type for hashes encoded in the Modular Crypt Format (MCF), +/// e.g. `$$...`. /// -/// For more information, see [`McfHash`]. +/// For more information, see [`PasswordHash`]. #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub struct McfHashRef<'a>(&'a str); +pub struct PasswordHashRef<'a>(&'a str); -impl<'a> McfHashRef<'a> { - /// Parse the given input string, returning an [`McfHashRef`] if valid. +impl<'a> PasswordHashRef<'a> { + /// Parse the given input string, returning an [`PasswordHashRef`] if valid. pub fn new(s: &'a str) -> Result { validate(s)?; Ok(Self(s)) @@ -69,20 +70,20 @@ impl<'a> McfHashRef<'a> { } } -impl<'a> From> for &'a str { - fn from(hash: McfHashRef<'a>) -> &'a str { +impl<'a> From> for &'a str { + fn from(hash: PasswordHashRef<'a>) -> &'a str { hash.0 } } #[cfg(feature = "alloc")] -impl From> for alloc::string::String { - fn from(hash: McfHashRef<'_>) -> Self { +impl From> for alloc::string::String { + fn from(hash: PasswordHashRef<'_>) -> Self { hash.0.into() } } -impl<'a> TryFrom<&'a str> for McfHashRef<'a> { +impl<'a> TryFrom<&'a str> for PasswordHashRef<'a> { type Error = Error; fn try_from(s: &'a str) -> Result { @@ -92,11 +93,14 @@ impl<'a> TryFrom<&'a str> for McfHashRef<'a> { #[cfg(feature = "alloc")] mod allocating { - use crate::{Base64, Error, Field, Fields, McfHashRef, Result, fields, validate, validate_id}; + use crate::{ + Base64, Error, Field, Fields, PasswordHashRef, Result, fields, validate, validate_id, + }; use alloc::string::String; use core::{fmt, str}; - /// Modular Crypt Format (MCF) serialized password hash. + /// Password hash encoded in the Modular Crypt Format (MCF). Owned form with builder + /// functionality. /// /// Password hashes in this format take the form `${id}$...`, where `{id}` is a short numeric or /// alphanumeric algorithm identifier optionally containing a `-`, followed by `$` as a delimiter, @@ -111,17 +115,17 @@ mod allocating { /// $6$rounds=100000$exn6tVc2j/MZD8uG$BI1Xh8qQSK9J4m14uwy7abn.ctj/TIAzlaVCto0MQrOFIeTXsc1iwzH16XEWo/a7c7Y9eVJvufVzYAs4EsPOy0 /// ``` #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] - pub struct McfHash(String); + pub struct PasswordHash(String); - impl McfHash { - /// Parse the given input string, returning an [`McfHash`] if valid. - pub fn new(s: impl Into) -> Result { + impl PasswordHash { + /// Parse the given input string, returning an [`PasswordHash`] if valid. + pub fn new(s: impl Into) -> Result { let s = s.into(); validate(&s)?; Ok(Self(s)) } - /// Create an [`McfHash`] from an identifier. + /// Create an [`PasswordHash`] from an identifier. /// /// # Returns /// @@ -129,7 +133,7 @@ mod allocating { /// /// Allowed characters match the regex: `[a-z0-9\-]`, where the first and last characters do NOT /// contain a `-`. - pub fn from_id(id: &str) -> Result { + pub fn from_id(id: &str) -> Result { validate_id(id)?; // TODO(tarcieri): overestimate capacity so most password hashes fit? @@ -144,9 +148,9 @@ mod allocating { &self.0 } - /// Get an [`McfHashRef`] which corresponds to this owned [`McfHash`]. - pub fn as_mcf_hash_ref(&self) -> McfHashRef<'_> { - McfHashRef(self.as_str()) + /// Get an [`PasswordHashRef`] which corresponds to this owned [`PasswordHash`]. + pub fn as_mcf_hash_ref(&self) -> PasswordHashRef<'_> { + PasswordHashRef(self.as_str()) } /// Get the algorithm identifier for this MCF hash. @@ -186,25 +190,25 @@ mod allocating { } } - impl<'a> AsRef for McfHashRef<'a> { + impl<'a> AsRef for PasswordHashRef<'a> { fn as_ref(&self) -> &str { self.as_str() } } - impl AsRef for McfHash { + impl AsRef for PasswordHash { fn as_ref(&self) -> &str { self.as_str() } } - impl From for String { - fn from(hash: McfHash) -> Self { + impl From for String { + fn from(hash: PasswordHash) -> Self { hash.0 } } - impl TryFrom for McfHash { + impl TryFrom for PasswordHash { type Error = Error; fn try_from(s: String) -> Result { @@ -212,7 +216,7 @@ mod allocating { } } - impl TryFrom<&str> for McfHash { + impl TryFrom<&str> for PasswordHash { type Error = Error; fn try_from(s: &str) -> Result { @@ -220,13 +224,13 @@ mod allocating { } } - impl fmt::Display for McfHash { + impl fmt::Display for PasswordHash { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } - impl str::FromStr for McfHash { + impl str::FromStr for PasswordHash { type Err = Error; fn from_str(s: &str) -> Result { diff --git a/mcf/tests/mcf.rs b/mcf/tests/mcf.rs index cec06f741..abefe09b5 100644 --- a/mcf/tests/mcf.rs +++ b/mcf/tests/mcf.rs @@ -3,7 +3,7 @@ #![cfg(feature = "alloc")] use hex_literal::hex; -use mcf::{Base64, McfHash}; +use mcf::{Base64, PasswordHash}; const SHA512_HASH: &str = "$6$rounds=100000$exn6tVc2j/MZD8uG$BI1Xh8qQSK9J4m14uwy7abn.ctj/TIAzlaVCto0MQrOFIeTXsc1iwzH16XEWo/a7c7Y9eVJvufVzYAs4EsPOy0"; @@ -14,31 +14,31 @@ const EXAMPLE_HASH: &[u8] = &hex!( #[test] fn from_id() { - let mcf_hash = McfHash::from_id("6").unwrap(); + let mcf_hash = PasswordHash::from_id("6").unwrap(); assert_eq!("$6", mcf_hash.as_str()); } #[test] fn parse_malformed() { - assert!("Hello, world!".parse::().is_err()); - assert!("$".parse::().is_err()); - assert!("$$".parse::().is_err()); - assert!("$$foo".parse::().is_err()); - assert!("$foo$".parse::().is_err()); - assert!("$-$foo".parse::().is_err()); - assert!("$foo-$bar".parse::().is_err()); - assert!("$-foo$bar".parse::().is_err()); + assert!("Hello, world!".parse::().is_err()); + assert!("$".parse::().is_err()); + assert!("$$".parse::().is_err()); + assert!("$$foo".parse::().is_err()); + assert!("$foo$".parse::().is_err()); + assert!("$-$foo".parse::().is_err()); + assert!("$foo-$bar".parse::().is_err()); + assert!("$-foo$bar".parse::().is_err()); } #[test] fn parse_id_only() { - let hash: McfHash = "$6".parse().unwrap(); + let hash: PasswordHash = "$6".parse().unwrap(); assert_eq!("6", hash.id()); } #[test] fn parse_sha512_hash() { - let hash: McfHash = SHA512_HASH.parse().unwrap(); + let hash: PasswordHash = SHA512_HASH.parse().unwrap(); assert_eq!("6", hash.id()); let mut fields = hash.fields(); @@ -64,7 +64,7 @@ fn parse_sha512_hash() { #[test] fn push_fields() { - let mut hash = McfHash::new("$6$rounds=100000").unwrap(); + let mut hash = PasswordHash::new("$6$rounds=100000").unwrap(); hash.push_base64(EXAMPLE_SALT, Base64::ShaCrypt); hash.push_base64(EXAMPLE_HASH, Base64::ShaCrypt); assert_eq!(SHA512_HASH, hash.as_str());