use std::time::{SystemTime, UNIX_EPOCH};
use bcrypt::{hash, verify, DEFAULT_COST};
use hmac::{Hmac, Mac};
use jwt::{SignWithKey, VerifyWithKey};
use rand::{distributions::Alphanumeric, Rng};
use sha2::Sha256;
use uuid::Uuid;
use crate::error::{Error, Result};
pub struct PasswordUtils;
impl PasswordUtils {
pub fn hash_password(password: &str) -> Result<String> {
hash(password, DEFAULT_COST).map_err(|e| Error::System(e.to_string()))
}
pub fn verify_password(password: &str, hash: &str) -> Result<bool> {
verify(password, hash).map_err(|e| Error::System(e.to_string()))
}
pub fn generate_password(length: usize) -> String {
rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(length)
.map(char::from)
.collect()
}
}
pub struct TokenUtils;
impl TokenUtils {
pub fn generate_token<T: serde::Serialize>(claims: &T, secret: &str) -> Result<String> {
let key: Hmac<Sha256> =
Hmac::new_from_slice(secret.as_bytes()).map_err(|e| Error::System(e.to_string()))?;
claims
.sign_with_key(&key)
.map_err(|e| Error::System(e.to_string()))
}
pub fn verify_token<T: serde::de::DeserializeOwned>(token: &str, secret: &str) -> Result<T> {
let key: Hmac<Sha256> =
Hmac::new_from_slice(secret.as_bytes()).map_err(|e| Error::System(e.to_string()))?;
token
.verify_with_key(&key)
.map_err(|e| Error::System(e.to_string()))
}
pub fn generate_uuid() -> String {
Uuid::new_v4().to_string()
}
pub fn current_timestamp() -> i64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs() as i64
}
}
pub struct CryptoUtils;
impl CryptoUtils {
pub fn random_string(length: usize) -> String {
rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(length)
.map(char::from)
.collect()
}
pub fn sha256(data: &[u8]) -> Vec<u8> {
use sha2::Digest;
let mut hasher = Sha256::new();
hasher.update(data);
hasher.finalize().to_vec()
}
pub fn hmac_sign(key: &[u8], data: &[u8]) -> Result<Vec<u8>> {
let mut mac =
Hmac::<Sha256>::new_from_slice(key).map_err(|e| Error::System(e.to_string()))?;
mac.update(data);
Ok(mac.finalize().into_bytes().to_vec())
}
pub fn hmac_verify(key: &[u8], data: &[u8], signature: &[u8]) -> Result<bool> {
let mut mac =
Hmac::<Sha256>::new_from_slice(key).map_err(|e| Error::System(e.to_string()))?;
mac.update(data);
Ok(mac.verify_slice(signature).is_ok())
}
}