regitry_code/
lib.rs

1/// src/lib.rs
2
3// 这个库提供生成和解码注册码的功能。
4// 注册码用于验证用户身份和授权,包含用户信息和有效期。
5// 使用 SM2 国密算法对注册码进行加密和解密,确保安全性。
6
7use chrono::{Utc, Duration}; // 用于处理日期和时间
8use smcrypto::sm2; // 用于 SM2 加密和解密
9use base64; // 用于 base64 编码和解码
10use std::fs;
11use smcrypto::sm3::sm3_hash; // SM3 哈希算法
12use rand::Rng;
13use std::str;
14// 生成注册码
15//
16// 参数:
17//   email: 邮箱地址
18//   days: 有效期天数
19//   public_key: SM2 公钥
20//
21// 返回值:
22//   注册码字符串
23pub fn generate_code(email: &str, days: i64, public_key: &str) -> String {
24    let enc_ctx = sm2::Encrypt::new(public_key);
25
26    // 计算有效期
27    let now = Utc::now();
28    let expire_time = now + Duration::days(days);
29
30    // 将 email 和有效期拼接成字符串
31    let data = format!("{}|{}", email, expire_time.to_rfc3339());
32
33    // 加密数据
34    let encrypted_data = enc_ctx.encrypt(data.as_bytes());
35
36    // 先进行 hex 编码
37    let encrypted_hex = hex::encode(encrypted_data);
38
39    // 再进行 base64 编码
40    let code = base64::encode(encrypted_hex);
41
42    code
43}
44
45// 解码注册码
46//
47// 参数:
48//   code: 注册码字符串
49//   private_key: SM2 私钥
50//
51// 返回值:
52//   (邮箱地址, 有效期截止时间)
53pub fn decode_code(code: &str, private_key: &str) -> (String, chrono::DateTime<Utc>) {
54    let dec_ctx = sm2::Decrypt::new(private_key);
55
56    // 先进行 base64 解码
57    let encrypted_hex = base64::decode(code).expect("Decoding base64 failed");
58
59    // 再进行 hex 解码
60    let encrypted_data = hex::decode(String::from_utf8(encrypted_hex).expect("Invalid UTF-8")).expect("Decoding hex failed");
61
62    // 解密数据
63    let decrypted_data = dec_ctx.decrypt(&encrypted_data);
64    let data = String::from_utf8(decrypted_data).expect("Invalid UTF-8");
65
66    // 解析 email 和有效期
67    let parts: Vec<&str> = data.split('|').collect();
68    if parts.len() == 2 {
69        let email = parts[0].to_string();
70        let expire_time = chrono::DateTime::parse_from_rfc3339(parts[1])
71            .expect("Invalid expire time format")
72            .with_timezone(&Utc); // 确保时区正确
73        (email, expire_time)
74    } else {
75        panic!("Invalid code format");
76    }
77}
78
79pub fn read_key_file(key_path: String) -> String {
80    let hex = fs::read_to_string(key_path).expect("Reading key failed");
81
82    let bytes = hex::decode(hex).expect("Decoding key failed");
83
84    String::from_utf8(bytes).expect("Invalid UTF-8")
85}
86
87
88
89
90// 生成随机字符串函数
91#[cfg(feature = "password")]
92pub fn generate_random_string(length: usize) -> String {
93    let charset: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
94    let mut rng = rand::thread_rng();
95    let random_string: String = (0..length)
96        .map(|_| {
97            let idx = rng.gen_range(0..charset.len());
98            charset[idx] as char
99        })
100        .collect();
101    random_string
102}
103
104// 加密密码函数
105#[cfg(feature = "password")]
106pub fn encrypt_password(password: &str, salt: &str) -> String {
107    // 将密码和盐值拼接
108    let data = format!("{}{}", password, salt);
109
110    // 使用 SM3 哈希算法进行加密
111    let hash_result = sm3_hash(data.as_bytes());
112
113    // 将加密结果转换为 Base64 字符串
114    base64::encode(hash_result)
115}
116
117// 验证密码函数
118#[cfg(feature = "password")]
119pub fn verify_password(password: &str, salt: &str, encrypted_password: &str) -> bool {
120    // 重新加密密码
121    let new_encrypted_password = encrypt_password(password, salt);
122
123    // 比较两个加密结果是否相同
124    new_encrypted_password == encrypted_password
125}
126
127use time::{OffsetDateTime, format_description};
128
129#[cfg(feature = "code-utils")]
130pub fn generate_task_number() -> String {
131    // 获取当前时间戳(精确到秒)
132    let now = OffsetDateTime::now_utc();
133    let timestamp = now.unix_timestamp(); // 获取 Unix 时间戳
134
135    // 格式化时间戳为字符串(例如:20231012_153045)
136    let format = format_description::parse("[year][month][day]_[hour][minute][second]").unwrap();
137    let time_str = now.format(&format).unwrap();
138
139    // 生成随机字符串(例如:4位随机字母+数字)
140    let mut rng = rand::thread_rng();
141    let random_part: String = (0..4)
142        .map(|_| {
143            let num = rng.gen_range(0..36); // 0-9 + a-z
144            if num < 10 {
145                (b'0' + num) as char // 数字 0-9
146            } else {
147                (b'a' + (num - 10)) as char // 字母 a-z
148            }
149        })
150        .collect();
151
152    // 组合时间戳和随机部分
153    format!("{}_{}", time_str, random_part)
154}