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