use argon2::{
password_hash::{rand_core::OsRng, SaltString},
Argon2, PasswordHash, PasswordHasher, PasswordVerifier, Params
};
use rand::RngCore;
use crate::error::{CasError, CasResult};
pub struct CASArgon;
impl CASArgon {
pub fn hash_password_parameters(memory_cost: u32, iterations: u32, parallelism: u32, password_to_hash: String) -> CasResult<String> {
let params = Params::new(memory_cost * 1024, iterations, parallelism, None)
.map_err(|_| CasError::InvalidParameters)?;
let argon2 = Argon2::new(argon2::Algorithm::Argon2id, argon2::Version::V0x13, params);
let salt = SaltString::generate(&mut OsRng);
let hash = argon2
.hash_password(password_to_hash.as_bytes(), &salt)
.map_err(|_| CasError::PasswordHashingFailed)?;
Ok(hash.to_string())
}
pub fn derive_aes_128_key(password: Vec<u8>) -> CasResult<Vec<u8>> {
let mut rng = OsRng;
let mut salt: [u8; 16] = [0; 16];
rng.fill_bytes(&mut salt);
let mut key = Box::new([0u8; 16]);
Argon2::default()
.hash_password_into(password.as_ref(), &salt, &mut *key)
.map_err(|_| CasError::PasswordHashingFailed)?;
Ok(key.to_vec())
}
pub fn derive_aes_256_key(password: Vec<u8>) -> CasResult<Vec<u8>> {
let mut rng = OsRng;
let mut salt: [u8; 16] = [0; 16];
rng.fill_bytes(&mut salt);
let mut key = Box::new([0u8; 32]);
Argon2::default()
.hash_password_into(password.as_ref(), &salt, &mut *key)
.map_err(|_| CasError::PasswordHashingFailed)?;
Ok(key.to_vec())
}
pub fn hash_password(password_to_hash: String) -> CasResult<String> {
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
let hashed_password = argon2
.hash_password(password_to_hash.as_bytes(), &salt)
.map_err(|_| CasError::PasswordHashingFailed)?
.to_string();
Ok(hashed_password)
}
pub fn verify_password(hashed_password: String, password_to_verify: String) -> CasResult<bool> {
let hashed_password =
PasswordHash::new(&hashed_password).map_err(|_| CasError::PasswordHashingFailed)?;
Ok(Argon2::default()
.verify_password(password_to_verify.as_bytes(), &hashed_password)
.is_ok())
}
}