use chrono::{Utc, Duration}; use smcrypto::sm2; use base64; use std::fs;
use smcrypto::sm3::sm3_hash; use rand::Rng;
use std::str;
pub fn generate_code(email: &str, days: i64, public_key: &str) -> String {
let enc_ctx = sm2::Encrypt::new(public_key);
let now = Utc::now();
let expire_time = now + Duration::days(days);
let data = format!("{}|{}", email, expire_time.to_rfc3339());
let encrypted_data = enc_ctx.encrypt(data.as_bytes());
let encrypted_hex = hex::encode(encrypted_data);
let code = base64::encode(encrypted_hex);
code
}
pub fn decode_code(code: &str, private_key: &str) -> (String, chrono::DateTime<Utc>) {
let dec_ctx = sm2::Decrypt::new(private_key);
let encrypted_hex = base64::decode(code).expect("Decoding base64 failed");
let encrypted_data = hex::decode(String::from_utf8(encrypted_hex).expect("Invalid UTF-8")).expect("Decoding hex failed");
let decrypted_data = dec_ctx.decrypt(&encrypted_data);
let data = String::from_utf8(decrypted_data).expect("Invalid UTF-8");
let parts: Vec<&str> = data.split('|').collect();
if parts.len() == 2 {
let email = parts[0].to_string();
let expire_time = chrono::DateTime::parse_from_rfc3339(parts[1])
.expect("Invalid expire time format")
.with_timezone(&Utc); (email, expire_time)
} else {
panic!("Invalid code format");
}
}
pub fn read_key_file(key_path: String) -> String {
let hex = fs::read_to_string(key_path).expect("Reading key failed");
let bytes = hex::decode(hex).expect("Decoding key failed");
String::from_utf8(bytes).expect("Invalid UTF-8")
}
#[cfg(feature = "password")]
pub fn generate_random_string(length: usize) -> String {
let charset: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
let mut rng = rand::thread_rng();
let random_string: String = (0..length)
.map(|_| {
let idx = rng.gen_range(0..charset.len());
charset[idx] as char
})
.collect();
random_string
}
#[cfg(feature = "password")]
pub fn encrypt_password(password: &str, salt: &str) -> String {
let data = format!("{}{}", password, salt);
let hash_result = sm3_hash(data.as_bytes());
base64::encode(hash_result)
}
#[cfg(feature = "password")]
pub fn verify_password(password: &str, salt: &str, encrypted_password: &str) -> bool {
let new_encrypted_password = encrypt_password(password, salt);
new_encrypted_password == encrypted_password
}
use time::{OffsetDateTime, format_description};
#[cfg(feature = "code-utils")]
pub fn generate_task_number() -> String {
let now = OffsetDateTime::now_utc();
let timestamp = now.unix_timestamp();
let format = format_description::parse("[year][month][day]_[hour][minute][second]").unwrap();
let time_str = now.format(&format).unwrap();
let mut rng = rand::thread_rng();
let random_part: String = (0..4)
.map(|_| {
let num = rng.gen_range(0..36); if num < 10 {
(b'0' + num) as char } else {
(b'a' + (num - 10)) as char }
})
.collect();
format!("{}_{}", time_str, random_part)
}