use std::{ fs::File, time::{SystemTime, UNIX_EPOCH}, }; use password_hash::{PasswordHash, PasswordHasher, SaltString}; use pbkdf2::{Params, Pbkdf2}; use serde::{de::DeserializeOwned, Serialize}; #[must_use] pub fn load_or_create_config(path: &str) -> T where T: Default + Serialize + DeserializeOwned, { std::fs::read_to_string(path).map_or_else( |_| { let defaults = T::default(); std::fs::write(path, toml::to_string(&defaults).unwrap()).unwrap(); defaults }, |data| toml::from_str(&data).unwrap(), ) } #[must_use] pub fn open_secret_key() -> Result { File::open("assets/security/client_secret_key.ec2b") } #[must_use] pub fn cur_timestamp_ms() -> u64 { SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_millis() as u64 } #[must_use] pub fn cur_timestamp() -> u64 { SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_secs() as u64 } #[must_use] pub fn hash_string(content: &str) -> Result { let salt = SaltString::generate(rand::thread_rng()); let hash = Pbkdf2.hash_password_customized( content.as_bytes(), None, None, Params { rounds: 10000, output_length: 32, }, &salt, )?; Ok(hash.serialize().to_string()) } #[must_use] pub fn verify_hash(content: &str, hash_str: &str) -> Option<()> { let hash = PasswordHash::new(hash_str).ok()?; hash.verify_password(&[&Pbkdf2], content).ok() }