argon2_async/
hasher.rs

1use crate::{Config, Error, Result};
2use argon2::{Argon2, Params, PasswordHasher};
3use password_hash::{Salt, SaltString};
4
5pub(crate) async fn get_hasher<'a>() -> Result<Argon2<'a>> {
6    let config = crate::config::GLOBAL_CONFIG
7        .get()
8        .ok_or(Error::MissingConfig)?
9        .read()
10        .await;
11
12    let Config {
13        algorithm,
14        version,
15        secret_key,
16        memory_cost,
17        iterations,
18        parallelism,
19        output_length,
20    } = *config;
21    let params = Params::new(memory_cost, iterations, parallelism, output_length)?;
22    Ok(match secret_key {
23        Some(key) => Argon2::new_with_secret(key, algorithm, version, params),
24        None => Ok(Argon2::new(algorithm, version, params)),
25    }?)
26}
27
28/// Hash this password with the given config. Return the hashed password as a raw bytes vector.
29///
30/// # Errors
31/// This function errors if any of the following happen:
32/// * the given config is invalid
33/// * hashing the password fails
34/// * communication between threads fails
35pub async fn hash_raw(password: impl AsRef<[u8]>) -> crate::Result<Vec<u8>> {
36    let hasher = get_hasher().await?;
37    let password = password.as_ref().to_owned();
38
39    let res = tokio::task::spawn_blocking(move || {
40        let salt_str = SaltString::generate(rand::thread_rng());
41        let salt = salt_str.as_salt();
42        let mut output = Vec::new();
43        hasher
44            .hash_password_into(&*password, salt.as_bytes(), &mut output)
45            .map(|_| output)
46    });
47
48    Ok(res.await??)
49}
50
51/// Hash this password with the given config. Return the hashed password as a String.
52///
53/// # Errors
54/// This function errors if any of the following happen:
55/// * the given config is invalid
56/// * hashing the password fails
57/// * communication between threads fails
58pub async fn hash(password: impl AsRef<[u8]>) -> crate::Result<String> {
59    let hasher = get_hasher().await?;
60    let password = password.as_ref().to_owned();
61
62    let res = tokio::task::spawn_blocking(move || {
63        let salt_str = SaltString::generate(rand::thread_rng());
64        let salt = Salt::from(&salt_str);
65        hasher
66            .hash_password(&*password, &salt)
67            .map(|x| x.serialize().to_string())
68    });
69
70    Ok(res.await??)
71}