diff --git a/Cargo.lock b/Cargo.lock index 8467c753..584a6e10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -270,8 +270,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "password-hash" version = "0.3.0-pre.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f27d413faa599d728b91e2a14907d05732112cb72cfaf8cf9e169e6617b5ae4" +source = "git+https://github.com/rustcrypto/traits.git#9e0de9d0aa33f0a7c687d7ae0809e3194027ba6c" dependencies = [ "base64ct", "rand_core", diff --git a/Cargo.toml b/Cargo.toml index 1f251097..bce2bf21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,6 @@ members = [ "scrypt", "sha-crypt" ] + +[patch.crates-io] +password-hash = { git = "https://github.com/rustcrypto/traits.git" } diff --git a/argon2/src/lib.rs b/argon2/src/lib.rs index 8b8da259..08368ad3 100644 --- a/argon2/src/lib.rs +++ b/argon2/src/lib.rs @@ -43,7 +43,7 @@ //! let argon2 = Argon2::default(); //! //! // Hash password to PHC string ($argon2id$v=19$...) -//! let password_hash = argon2.hash_password_simple(password, salt.as_ref()).unwrap().to_string(); +//! let password_hash = argon2.hash_password(password, salt.as_ref()).unwrap().to_string(); //! //! // Verify password against PHC string //! let parsed_hash = PasswordHash::new(&password_hash).unwrap(); @@ -106,7 +106,7 @@ use core::convert::TryFrom; #[cfg(feature = "password-hash")] use { core::convert::TryInto, - password_hash::{Ident, Salt}, + password_hash::{Decimal, Ident, Salt}, }; /// Minimum and maximum number of lanes (degree of parallelism) @@ -395,7 +395,7 @@ impl<'key> Argon2<'key> { impl PasswordHasher for Argon2<'_> { type Params = Params; - fn hash_password_simple<'a, S>( + fn hash_password<'a, S>( &self, password: &[u8], salt: &'a S, @@ -426,10 +426,11 @@ impl PasswordHasher for Argon2<'_> { }) } - fn hash_password<'a>( + fn hash_password_customized<'a>( &self, password: &[u8], alg_id: Option>, + version: Option, params: Params, salt: impl Into>, ) -> password_hash::Result> { @@ -445,14 +446,17 @@ impl PasswordHasher for Argon2<'_> { params.t_cost, params.m_cost, params.p_cost, - params.version, + version + .map(Version::try_from) + .transpose()? + .unwrap_or_else(|| params.version), )?; // TODO(tarcieri): pass these via `Params` when `Argon::new` accepts `Params` hasher.algorithm = Some(algorithm); hasher.output_size = Some(params.output_size); - hasher.hash_password_simple(password, salt.as_str()) + hasher.hash_password(password, salt.as_str()) } } @@ -498,7 +502,8 @@ mod tests { // Too short after decoding let salt = Salt::new("somesalt").unwrap(); - let res = argon2.hash_password(EXAMPLE_PASSWORD, None, Params::default(), salt); + let res = + argon2.hash_password_customized(EXAMPLE_PASSWORD, None, None, Params::default(), salt); assert_eq!( res, Err(password_hash::Error::SaltInvalid( @@ -517,7 +522,7 @@ mod tests { let hasher = Argon2::new(None, t_cost, m_cost, p_cost, version).unwrap(); let hash = hasher - .hash_password_simple(EXAMPLE_PASSWORD, EXAMPLE_SALT) + .hash_password(EXAMPLE_PASSWORD, EXAMPLE_SALT) .unwrap(); assert_eq!(hash.version.unwrap(), version.into()); diff --git a/pbkdf2/src/lib.rs b/pbkdf2/src/lib.rs index f9f49dcb..50b13d41 100644 --- a/pbkdf2/src/lib.rs +++ b/pbkdf2/src/lib.rs @@ -39,7 +39,7 @@ //! let salt = SaltString::generate(&mut OsRng); //! //! // Hash password to PHC string ($pbkdf2-sha256$...) -//! let password_hash = Pbkdf2.hash_password_simple(password, salt.as_ref()).unwrap().to_string(); +//! let password_hash = Pbkdf2.hash_password(password, salt.as_ref()).unwrap().to_string(); //! //! // Verify password against PHC string //! let parsed_hash = PasswordHash::new(&password_hash).unwrap(); diff --git a/pbkdf2/src/simple.rs b/pbkdf2/src/simple.rs index 14c24a39..5f092771 100644 --- a/pbkdf2/src/simple.rs +++ b/pbkdf2/src/simple.rs @@ -10,7 +10,7 @@ use core::{ }; use hmac::Hmac; use password_hash::{ - errors::InvalidValue, Error, Ident, McfHasher, Output, ParamsString, PasswordHash, + errors::InvalidValue, Decimal, Error, Ident, McfHasher, Output, ParamsString, PasswordHash, PasswordHasher, Result, Salt, }; use sha2::{Sha256, Sha512}; @@ -36,14 +36,21 @@ pub struct Pbkdf2; impl PasswordHasher for Pbkdf2 { type Params = Params; - fn hash_password<'a>( + fn hash_password_customized<'a>( &self, password: &[u8], alg_id: Option>, + version: Option, params: Params, salt: impl Into>, ) -> Result> { let algorithm = Algorithm::try_from(alg_id.unwrap_or(PBKDF2_SHA256))?; + + // Versions unsupported + if version.is_some() { + return Err(Error::Version); + } + let salt = salt.into(); let mut salt_arr = [0u8; 64]; let salt_bytes = salt.b64_decode(&mut salt_arr)?; diff --git a/pbkdf2/tests/simple.rs b/pbkdf2/tests/simple.rs index a19f43da..2c81b2f7 100644 --- a/pbkdf2/tests/simple.rs +++ b/pbkdf2/tests/simple.rs @@ -30,7 +30,7 @@ fn hash_with_default_algorithm() { }; let hash = Pbkdf2 - .hash_password(PASSWORD.as_bytes(), None, params, salt) + .hash_password_customized(PASSWORD.as_bytes(), None, None, params, salt) .unwrap(); assert_eq!(hash.algorithm, Algorithm::Pbkdf2Sha256.ident()); diff --git a/scrypt/src/lib.rs b/scrypt/src/lib.rs index 838f5dc7..8eb10d82 100644 --- a/scrypt/src/lib.rs +++ b/scrypt/src/lib.rs @@ -25,7 +25,7 @@ //! let salt = SaltString::generate(&mut OsRng); //! //! // Hash password to PHC string ($scrypt$...) -//! let password_hash = Scrypt.hash_password_simple(password, salt.as_ref()).unwrap().to_string(); +//! let password_hash = Scrypt.hash_password(password, salt.as_ref()).unwrap().to_string(); //! //! // Verify password against PHC string //! let parsed_hash = PasswordHash::new(&password_hash).unwrap(); diff --git a/scrypt/src/simple.rs b/scrypt/src/simple.rs index c300acdd..6a1d87c7 100644 --- a/scrypt/src/simple.rs +++ b/scrypt/src/simple.rs @@ -4,8 +4,8 @@ use crate::{scrypt, Params}; use base64ct::{Base64, Encoding}; use core::convert::TryInto; use password_hash::{ - errors::InvalidValue, Error, Ident, McfHasher, Output, PasswordHash, PasswordHasher, Result, - Salt, + errors::InvalidValue, Decimal, Error, Ident, McfHasher, Output, PasswordHash, PasswordHasher, + Result, Salt, }; /// Algorithm identifier @@ -19,16 +19,21 @@ pub struct Scrypt; impl PasswordHasher for Scrypt { type Params = Params; - fn hash_password<'a>( + fn hash_password_customized<'a>( &self, password: &[u8], alg_id: Option>, + version: Option, params: Params, salt: impl Into>, ) -> Result> { - match alg_id { - Some(ALG_ID) | None => (), - _ => return Err(Error::Algorithm), + if !matches!(alg_id, Some(ALG_ID) | None) { + return Err(Error::Algorithm); + } + + // Versions unsupported + if version.is_some() { + return Err(Error::Version); } let salt = salt.into();