LukeMathWalker / zero-to-production

Code for "Zero To Production In Rust", a book on API development using Rust.
https://www.zero2prod.com
Apache License 2.0
5.43k stars 470 forks source link

peppering the salted passwords #262

Closed geoHeil closed 2 weeks ago

geoHeil commented 4 weeks ago

In the book the exercise of peppering is left to the reader. I have to admit - new to rust I am struggling a bit

https://github.com/LukeMathWalker/zero-to-production/blob/main/src/authentication/password.rs#L118-L124

The code/book uses:

Argon2::new(
        Algorithm::Argon2id,
        Version::V0x13,
        Params::new(15000, 2, 1, None).unwrap(),
    )
    .hash_password(password.expose_secret().as_bytes(), &salt)?

I already figured out I have to use:

Argon2::new_with_secret(
        "secret_pepper".as_bytes(),
        Algorithm::Argon2id,
        Version::V0x13,
        Params::new(19000, 2, 1, None).unwrap(),
    )?
    .hash_password(password.expose_secret().as_bytes(), &salt)?

when computing the hashes.

However, I am stuck for validating as:

Argon2::default()
        .verify_password(
            password_candidate.expose_secret().as_bytes(),
            &expected_password_hash,
        )

does not support passing in the pepper.

Would I need to re-implement:

impl<T: PasswordHasher> PasswordVerifier for T {
    fn verify_password(&self, password: &[u8], hash: &PasswordHash<'_>) -> Result<()> {

this interface? Or am I overlooking a more native way of handling this? Even trying:

let password_hasher = Argon2::new_with_secret(
    "secret_pepper".as_bytes(),
    Algorithm::Argon2id,
    Version::V0x13,
    Params::new(19000, 2, 1, None).unwrap()
);
password_hasher.unwrap().verify_password(
    password_candidate.expose_secret().as_bytes(),
    &expected_password_hash,
)
    .context("Invalid password.")
    .map_err(AuthError::InvalidCredentials)

does not work, i.e. the validation of the passwords fails:

 Err(
    Password,
)
thread 'change_password::changing_password_works' panicked at tests/api/helpers.rs:301:5:
assertion `left == right` failed
  left: "/login"
 right: "/admin/dashboard"
geoHeil commented 2 weeks ago

my bad - the code above works fine. I had a bug in the unit test bootstrapping code - and there the pepper was not set correctly