support_kit/encryption/
password_control.rs

1use crate::{Configuration, Environment, PasswordError};
2use argon2::{password_hash::SaltString, Argon2, Params, PasswordHasher, PasswordVerifier};
3
4pub struct PasswordControl {
5    params: Params,
6}
7
8impl PasswordControl {
9    pub fn test() -> Self {
10        let params = Params::new(8, 1, 1, Some(32)).unwrap();
11        Self { params }
12    }
13
14    pub fn from_config(config: Configuration) -> Self {
15        if let Some(Environment::Test) = config.environment {
16            Self::test()
17        } else {
18            Self::default()
19        }
20    }
21
22    pub fn hasher(&self) -> Argon2<'static> {
23        Argon2::new(
24            argon2::Algorithm::Argon2id,
25            argon2::Version::V0x13,
26            self.params.clone(),
27        )
28    }
29
30    /// Password generation creates an argon2 password hash from a given password.
31    #[tracing::instrument(level = "debug", name = "Generate password", skip(self, password))]
32    pub fn generate_password_hash(&self, password: &str) -> crate::Result<String> {
33        let salt = SaltString::generate(&mut rand::thread_rng());
34
35        Ok(self
36            .hasher()
37            .hash_password(password.as_bytes(), &salt)
38            .map_err(PasswordError::from)?
39            .to_string())
40    }
41
42    /// Validate a password against a password hash.
43    #[tracing::instrument(
44        level = "debug",
45        name = "Verifying password",
46        skip(self, password, password_hash)
47    )]
48    pub fn validate_password_hash(
49        &self,
50        password: &str,
51        password_hash: &str,
52    ) -> Result<(), argon2::password_hash::Error> {
53        let password = String::from(password);
54        let password_hash = String::from(password_hash);
55
56        let hash = argon2::PasswordHash::new(&password_hash)?;
57
58        self.hasher().verify_password(password.as_bytes(), &hash)
59    }
60}
61
62impl Default for PasswordControl {
63    fn default() -> Self {
64        let params = Params::default();
65        Self { params }
66    }
67}