#[cfg(feature = "rand")]
use rand::Rng;
#[cfg(feature = "hash")]
use pbkdf2::{
password_hash::{rand_core::OsRng, PasswordHasher, SaltString},
Pbkdf2,
};
pub const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789";
#[cfg(feature = "rand")]
pub fn generate_random_string(length: usize) -> String {
let mut rng = rand::thread_rng();
let mut random_string = String::new();
for _ in 0..length {
let random_char = CHARSET[rng.gen_range(0..CHARSET.len())] as char;
random_string.push(random_char);
}
random_string
}
#[derive(Default, Clone, Debug)]
pub enum HashingAlgorithm {
#[default]
Pbkdf2,
}
impl HashingAlgorithm {
pub fn to_str(&self) -> &str {
match self {
HashingAlgorithm::Pbkdf2 => "Pbkdf2",
}
}
}
impl From<&str> for HashingAlgorithm {
fn from(s: &str) -> Self {
match s {
"Pbkdf2" => HashingAlgorithm::Pbkdf2,
_ => HashingAlgorithm::Pbkdf2,
}
}
}
#[cfg(feature = "hash")]
pub fn generate_hash(data: String, alg: HashingAlgorithm) -> Result<String, crate::Error> {
match alg {
HashingAlgorithm::Pbkdf2 => generate_hash_pdkdf2(data),
}
}
#[cfg(feature = "hash")]
pub(crate) fn generate_hash_pdkdf2(data: String) -> Result<String, crate::Error> {
let salt = SaltString::generate(&mut OsRng);
match Pbkdf2.hash_password(data.as_bytes(), &salt) {
Ok(hash) => Ok(hash.to_string()),
Err(e) => Err(crate::Error::HashingError(format!(
"Error hashing password: {}",
e
))),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[cfg(feature = "rand")]
fn test_generate_random_string() {
let random_string = generate_random_string(10);
assert_eq!(random_string.len(), 10);
}
}