argonautica icon indicating copy to clipboard operation
argonautica copied to clipboard

How to reuse a `Hasher` and `Verifier`?

Open little-dude opened this issue 5 years ago • 1 comments

I'd like to keep a hasher around and use it to hash password. Something like:

pub struct AuthService {
    secret_key: String,
    hasher: Hasher<'static>,
    verifier: Verifier<'static>,
}

impl AuthService {
    pub fn new(secret_key: String, hasher_iterations: u32, hasher_memory: u32) -> Self {
        let mut hasher = Hasher::default();
        hasher
            .configure_memory_size(hasher_memory)
            .configure_iterations(hasher_iterations);
        Self {
            secret_key,
            hasher,
            verifier: Verifier::default(),
        }
    }

    pub fn hash_password(&self, password: &str) -> String {
        self.hasher
            .with_password(password)
            .with_secret_key(&self.secret_key)
            .hash()
            .unwrap()
    }

    pub fn verify_password(&self, password: &str, hash: &str) -> bool {
        self.verifier
            .with_hash(hash)
            .with_password(password)
            .with_secret_key(&self.secret_key)
            .verify()
            .unwrap()
    }
}

But the problem is that the lifetime parameter of both Hasher and Verifier are tied to the lifetime of the password itself. With the code above, the compiler expects my passwords to have the 'static lifetime:

  --> src/main.rs:25:14
   |
23 |     pub fn hash_password(&self, password: &str) -> String {
   |                                           ---- help: add explicit lifetime `'static` to the type of `password`: `&'static str`
24 |         self.hasher
25 |             .with_password(password)
   |              ^^^^^^^^^^^^^ lifetime `'static` required

error[E0621]: explicit lifetime required in the type of `password`
  --> src/main.rs:33:14
   |
31 |     pub fn verify_password(&self, password: &str, hash: &str) -> bool {
   |                                             ---- help: add explicit lifetime `'static` to the type of `password`: `&'static str`
32 |         self.verifier
33 |             .with_hash(hash)
   |              ^^^^^^^^^ lifetime `'static` required

My questions are:

  • does it make sense to reuse the Hasher and Verifier instead of always creating new ones? (edit: I guess this question is the same as https://github.com/bcmyers/argonautica/issues/22)
  • if it does make sense, how can this be achieved?

little-dude avatar Dec 05 '19 11:12 little-dude

Another solution is to turn the password and secret key into actual Strings, but again that seems rather inefficient:

pub struct AuthService {
    secret_key: String,
    hasher: Hasher<'static>,
    verifier: Verifier<'static>,
}

impl AuthService {
    pub fn new(secret_key: String, hasher_iterations: u32, hasher_memory: u32) -> Self {
        let mut hasher = Hasher::default();
        hasher
            .configure_memory_size(hasher_memory)
            .configure_iterations(hasher_iterations);
        Self {
            secret_key,
            hasher,
            verifier: Verifier::default(),
        }
    }

    pub fn hash_password(&mut self, password: &str) -> String {
        self.hasher
            .with_password(password.to_string())
            .with_secret_key(self.secret_key.clone())
            .hash()
            .unwrap()
    }

    pub fn verify_password(&mut self, password: &str, hash: &str) -> bool {
        self.verifier
            .with_hash(hash)
            .with_password(password.to_string())
            .with_secret_key(self.secret_key.clone())
            .verify()
            .unwrap()
    }
}

little-dude avatar Dec 05 '19 14:12 little-dude