Skip to content

Commit 2915b86

Browse files
authored
Remove Salt lifetime (#755)
Companion PR to RustCrypto/traits#2109
1 parent 9a459c3 commit 2915b86

File tree

14 files changed

+94
-110
lines changed

14 files changed

+94
-110
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

argon2/src/lib.rs

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,18 @@
3939
)]
4040
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
4141
//! use argon2::{
42-
//! password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, phc::SaltString},
42+
//! password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, phc::Salt},
4343
//! Argon2
4444
//! };
4545
//!
4646
//! let password = b"hunter42"; // Bad password; don't actually use!
47-
//! let salt = SaltString::generate(); // Note: needs the `getrandom` feature of `argon2` enabled
47+
//! let salt = Salt::generate(); // Note: needs the `getrandom` feature of `argon2` enabled
4848
//!
4949
//! // Argon2 with default params (Argon2id v19)
5050
//! let argon2 = Argon2::default();
5151
//!
5252
//! // Hash password to PHC string ($argon2id$v=19$...)
53-
//! let password_hash = argon2.hash_password(password, salt.as_ref())?.to_string();
53+
//! let password_hash = argon2.hash_password(password, &salt)?.to_string();
5454
//!
5555
//! // Verify password against PHC string.
5656
//! //
@@ -73,12 +73,12 @@
7373
)]
7474
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
7575
//! use argon2::{
76-
//! password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, phc::SaltString},
76+
//! password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, phc::Salt},
7777
//! Algorithm, Argon2, Params, Version
7878
//! };
7979
//!
8080
//! let password = b"hunter42"; // Bad password; don't actually use!
81-
//! let salt = SaltString::generate(); // Note: needs the `getrandom` feature of `argon2` enabled
81+
//! let salt = Salt::generate(); // Note: needs the `getrandom` feature of `argon2` enabled
8282
//!
8383
//! // Argon2 with default params (Argon2id v19) and pepper
8484
//! let argon2 = Argon2::new_with_secret(
@@ -90,7 +90,7 @@
9090
//! .unwrap();
9191
//!
9292
//! // Hash password to PHC string ($argon2id$v=19$...)
93-
//! let password_hash = argon2.hash_password(password, salt.as_ref())?.to_string();
93+
//! let password_hash = argon2.hash_password(password, &salt)?.to_string();
9494
//!
9595
//! // Verify password against PHC string.
9696
//! //
@@ -623,14 +623,14 @@ impl<'key> Argon2<'key> {
623623
impl CustomizedPasswordHasher for Argon2<'_> {
624624
type Params = Params;
625625

626-
fn hash_password_customized<'a>(
626+
fn hash_password_customized(
627627
&self,
628628
password: &[u8],
629-
alg_id: Option<&'a str>,
629+
salt: &[u8],
630+
alg_id: Option<&str>,
630631
version: Option<u32>,
631632
params: Params,
632-
salt: &'a str,
633-
) -> password_hash::Result<PasswordHash<'a>> {
633+
) -> password_hash::Result<PasswordHash> {
634634
let algorithm = alg_id
635635
.map(Algorithm::try_from)
636636
.transpose()?
@@ -655,22 +655,16 @@ impl CustomizedPasswordHasher for Argon2<'_> {
655655

656656
#[cfg(all(feature = "alloc", feature = "password-hash"))]
657657
impl PasswordHasher for Argon2<'_> {
658-
fn hash_password<'a>(
659-
&self,
660-
password: &[u8],
661-
salt: &'a str,
662-
) -> password_hash::Result<PasswordHash<'a>> {
663-
let salt = Salt::from_b64(salt)?;
664-
let mut salt_arr = [0u8; 64];
665-
let salt_bytes = salt.decode_b64(&mut salt_arr)?;
658+
fn hash_password(&self, password: &[u8], salt: &[u8]) -> password_hash::Result<PasswordHash> {
659+
let salt = Salt::new(salt)?;
666660

667661
let output_len = self
668662
.params
669663
.output_len()
670664
.unwrap_or(Params::DEFAULT_OUTPUT_LEN);
671665

672666
let output = Output::init_with(output_len, |out| {
673-
Ok(self.hash_password_into(password, salt_bytes, out)?)
667+
Ok(self.hash_password_into(password, &salt, out)?)
674668
})?;
675669

676670
Ok(PasswordHash {
@@ -704,17 +698,18 @@ mod tests {
704698
const EXAMPLE_PASSWORD: &[u8] = b"hunter42";
705699

706700
/// Example salt value. Don't use a static salt value!!!
707-
const EXAMPLE_SALT: &str = "examplesaltvalue";
701+
const EXAMPLE_SALT: &[u8] = b"example-salt";
708702

709703
#[test]
710704
fn decoded_salt_too_short() {
711705
let argon2 = Argon2::default();
712706

713-
// Too short after decoding
714-
let salt = "somesalt";
707+
// Too short: minimum size 8-bytes
708+
let salt = b"weesalt";
715709

716710
let res =
717-
argon2.hash_password_customized(EXAMPLE_PASSWORD, None, None, Params::default(), salt);
711+
argon2.hash_password_customized(EXAMPLE_PASSWORD, salt, None, None, Params::default());
712+
718713
assert_eq!(
719714
res,
720715
Err(password_hash::Error::SaltInvalid(

argon2/src/params.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,10 +397,10 @@ impl TryFrom<&ParamsString> for Params {
397397
}
398398

399399
#[cfg(feature = "password-hash")]
400-
impl<'a> TryFrom<&'a PasswordHash<'a>> for Params {
400+
impl TryFrom<&PasswordHash> for Params {
401401
type Error = password_hash::Error;
402402

403-
fn try_from(hash: &'a PasswordHash<'a>) -> password_hash::Result<Self> {
403+
fn try_from(hash: &PasswordHash) -> password_hash::Result<Self> {
404404
let mut params = Self::try_from(&hash.params)?;
405405

406406
if let Some(output) = &hash.hash {

argon2/tests/kat.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use argon2::{
1414
PasswordVerifier, Version,
1515
};
1616
use hex_literal::hex;
17-
use password_hash::phc::SaltString;
1817

1918
/// Params used by the KATs.
2019
fn example_params() -> Params {
@@ -367,11 +366,7 @@ fn hashtest(
367366
assert_eq!(out, expected_raw_hash);
368367

369368
// Test hash encoding
370-
let salt_string = SaltString::encode_b64(salt).unwrap();
371-
let phc_hash = ctx
372-
.hash_password(pwd, salt_string.as_ref())
373-
.unwrap()
374-
.to_string();
369+
let phc_hash = ctx.hash_password(pwd, salt).unwrap().to_string();
375370
assert_eq!(phc_hash, expected_phc_hash);
376371

377372
let hash = PasswordHash::new(alternative_phc_hash).unwrap();

argon2/tests/phc_strings.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ use argon2::{
88
Algorithm, Argon2, AssociatedData, KeyId, ParamsBuilder, PasswordHash, PasswordHasher,
99
PasswordVerifier, Version,
1010
};
11-
use password_hash::{
12-
errors::{Error, InvalidValue},
13-
phc::SaltString,
14-
};
11+
use password_hash::errors::{Error, InvalidValue};
1512

1613
/// Valid password
1714
pub const VALID_PASSWORD: &[u8] = b"password";
@@ -213,13 +210,9 @@ fn check_hash_encoding_parameters_order() {
213210

214211
let ctx = Argon2::new(Algorithm::Argon2d, Version::V0x10, params);
215212

216-
let salt = vec![0; 8];
217213
let password = b"password";
218-
let salt_string = SaltString::encode_b64(&salt).unwrap();
219-
let password_hash = ctx
220-
.hash_password(password, salt_string.as_ref())
221-
.unwrap()
222-
.to_string();
214+
let salt = [0u8; 8];
215+
let password_hash = ctx.hash_password(password, &salt).unwrap().to_string();
223216

224217
// The parameters shall appear in the m,t,p,keyid,data order
225218
assert_eq!(

balloon-hash/src/lib.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,19 @@
3232
#![cfg_attr(not(feature = "getrandom"), doc = "```ignore")]
3333
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
3434
//! use balloon_hash::{
35-
//! password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, phc::SaltString},
35+
//! password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, phc::Salt},
3636
//! Balloon
3737
//! };
3838
//! use sha2::Sha256;
3939
//!
4040
//! let password = b"hunter42"; // Bad password; don't actually use!
41-
//! let salt = SaltString::generate(); // Note: needs the `getrandom` feature of `balloon-hash` enabled
41+
//! let salt = Salt::generate(); // Note: needs the `getrandom` feature of `balloon-hash` enabled
4242
//!
4343
//! // Balloon with default params
4444
//! let balloon = Balloon::<Sha256>::default();
4545
//!
4646
//! // Hash password to PHC string ($balloon$v=1$...)
47-
//! let password_hash = balloon.hash_password(password, salt.as_str())?.to_string();
47+
//! let password_hash = balloon.hash_password(password, &salt)?.to_string();
4848
//!
4949
//! // Verify password against PHC string
5050
//! let parsed_hash = PasswordHash::new(&password_hash)?;
@@ -219,14 +219,14 @@ where
219219
{
220220
type Params = Params;
221221

222-
fn hash_password_customized<'a>(
222+
fn hash_password_customized(
223223
&self,
224224
password: &[u8],
225+
salt: &[u8],
225226
alg_id: Option<&str>,
226227
version: Option<Version>,
227228
params: Params,
228-
salt: &'a str,
229-
) -> password_hash::Result<PasswordHash<'a>> {
229+
) -> password_hash::Result<PasswordHash> {
230230
let algorithm = alg_id
231231
.map(Algorithm::try_from)
232232
.transpose()?
@@ -248,15 +248,9 @@ where
248248
D: Digest + FixedOutputReset,
249249
Array<u8, D::OutputSize>: ArrayDecoding,
250250
{
251-
fn hash_password<'a>(
252-
&self,
253-
password: &[u8],
254-
salt: &'a str,
255-
) -> password_hash::Result<PasswordHash<'a>> {
256-
let salt = Salt::from_b64(salt)?;
257-
let mut salt_arr = [0u8; 64];
258-
let salt_bytes = salt.decode_b64(&mut salt_arr)?;
259-
let output = Output::new(&self.hash(password, salt_bytes)?)?;
251+
fn hash_password(&self, password: &[u8], salt: &[u8]) -> password_hash::Result<PasswordHash> {
252+
let salt = Salt::new(salt)?;
253+
let output = Output::new(&self.hash(password, &salt)?)?;
260254

261255
Ok(PasswordHash {
262256
algorithm: self.algorithm.ident(),

balloon-hash/src/params.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,10 @@ impl TryFrom<&ParamsString> for Params {
106106
}
107107

108108
#[cfg(feature = "password-hash")]
109-
impl<'a> TryFrom<&'a PasswordHash<'a>> for Params {
109+
impl TryFrom<&PasswordHash> for Params {
110110
type Error = password_hash::Error;
111111

112-
fn try_from(hash: &'a PasswordHash<'a>) -> password_hash::Result<Self> {
112+
fn try_from(hash: &PasswordHash) -> password_hash::Result<Self> {
113113
Self::try_from(&hash.params)
114114
}
115115
}

balloon-hash/tests/balloon.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ fn hash_simple_retains_configured_params() {
8282
const EXAMPLE_PASSWORD: &[u8] = b"hunter42";
8383

8484
/// Example salt value. Don't use a static salt value!!!
85-
const EXAMPLE_SALT: &str = "examplesaltvalue";
85+
const EXAMPLE_SALT: &[u8] = b"example-salt";
8686

8787
// Non-default but valid parameters
8888
let t_cost = 4;

password-auth/src/lib.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub use crate::errors::{ParseError, VerifyError};
2828
use alloc::string::{String, ToString};
2929
use password_hash::{
3030
PasswordHasher, PasswordVerifier,
31-
phc::{ParamsString, PasswordHash, SaltString},
31+
phc::{ParamsString, PasswordHash, Salt},
3232
};
3333

3434
#[cfg(not(any(feature = "argon2", feature = "pbkdf2", feature = "scrypt")))]
@@ -48,18 +48,15 @@ use scrypt::Scrypt;
4848
/// Uses the best available password hashing algorithm given the enabled
4949
/// crate features (typically Argon2 unless explicitly disabled).
5050
pub fn generate_hash(password: impl AsRef<[u8]>) -> String {
51-
let salt = SaltString::generate();
52-
generate_phc_hash(password.as_ref(), salt.as_ref())
51+
let salt = Salt::generate();
52+
generate_phc_hash(password.as_ref(), &salt)
5353
.map(|hash| hash.to_string())
5454
.expect("password hashing error")
5555
}
5656

5757
/// Generate a PHC hash using the preferred algorithm.
5858
#[allow(unreachable_code)]
59-
fn generate_phc_hash<'a>(
60-
password: &[u8],
61-
salt: &'a str,
62-
) -> password_hash::Result<PasswordHash<'a>> {
59+
fn generate_phc_hash(password: &[u8], salt: &[u8]) -> password_hash::Result<PasswordHash> {
6360
//
6461
// Algorithms below are in order of preference
6562
//
@@ -163,11 +160,15 @@ mod tests {
163160

164161
#[cfg(feature = "pbkdf2")]
165162
mod pdkdf2 {
166-
use super::{EXAMPLE_PASSWORD, verify_password};
163+
use super::verify_password;
164+
165+
/// PBKDF2 password test vector from the `pbkdf2` crate
166+
const EXAMPLE_PASSWORD: &[u8] = b"passwordPASSWORDpassword";
167167

168-
/// PBKDF2 hash for the string "password".
169-
const EXAMPLE_HASH: &str =
170-
"$pbkdf2-sha256$i=4096,l=32$c2FsdA$xeR41ZKIyEGqUw22hFxMjZYok6ABzk4RpJY4c6qYE0o";
168+
/// PBKDF2 hash test vector from the `pbkdf2` crate
169+
const EXAMPLE_HASH: &str = "$pbkdf2-sha256$i=4096,l=40\
170+
$c2FsdFNBTFRzYWx0U0FMVHNhbHRTQUxUc2FsdFNBTFRzYWx0\
171+
$NIyJ28vTKy8y2BS4EW6EzysXNH68GAAYHE4qH7jdU+HGNVGMfaxH6Q";
171172

172173
#[test]
173174
fn verify() {

pbkdf2/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,15 @@
5959
#![cfg_attr(not(feature = "simple"), doc = "```ignore")]
6060
//! # fn main() -> Result<(), Box<dyn core::error::Error>> {
6161
//! use pbkdf2::{
62-
//! password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, phc::SaltString},
62+
//! password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, phc::Salt},
6363
//! Pbkdf2
6464
//! };
6565
//!
6666
//! let password = b"hunter42"; // Bad password; don't actually use!
67-
//! let salt = SaltString::generate();
67+
//! let salt = Salt::generate();
6868
//!
6969
//! // Hash password to PHC string ($pbkdf2-sha256$...)
70-
//! let password_hash = Pbkdf2.hash_password(password, salt.as_ref())?.to_string();
70+
//! let password_hash = Pbkdf2.hash_password(password, &salt)?.to_string();
7171
//!
7272
//! // Verify password against PHC string
7373
//! let parsed_hash = PasswordHash::new(&password_hash)?;

0 commit comments

Comments
 (0)