echoes/backend/src/secret.rs

119 lines
4.1 KiB
Rust
Raw Normal View History

// File path: src/secret.rs
/**
* JWT的生成和验证功能
* JWTJWT的相关函数
*/
use jwt_compact::{alg::Ed25519, AlgorithmExt, Header, Token, UntrustedToken, TimeOptions};
use serde::{Serialize, Deserialize};
use chrono::{Duration, Utc};
use ed25519_dalek::{SigningKey, VerifyingKey};
use std::fs::File;
use std::io::Write;
use std::{env, fs};
use std::error::Error;
use rand::{SeedableRng, RngCore};
// 定义JWT的Claims结构体有效载荷
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CustomClaims {
pub user_id: String, // 用户ID
pub device_ua: String, // 用户UA
}
pub enum SecretKey {
Signing, // 签名密钥
Verifying, // 验证密钥
}
impl SecretKey {
fn as_string(&self) -> String {
match self {
Self::Signing => String::from("signing"),
Self::Verifying => String::from("verifying"),
}
}
}
/**
*
*/
pub fn generate_key() -> Result<(), Box<dyn Error>> {
let mut csprng = rand::rngs::StdRng::from_entropy(); // 使用系统熵创建随机数生成器
let mut private_key_bytes = [0u8; 32]; // 存储签名密钥的字节数组
csprng.fill_bytes(&mut private_key_bytes); // 生成签名密钥
let signing_key = SigningKey::from_bytes(&private_key_bytes); // 从签名密钥获取SigningKey
let verifying_key = signing_key.verifying_key(); // 获取验证密钥
let base_path = env::current_dir()?
.join("assets")
.join("key");
fs::create_dir_all(&base_path)?; // 创建目录
File::create(base_path.join(SecretKey::Signing.as_string()))?
.write_all(signing_key.as_bytes())?; // 保存签名密钥
File::create(base_path.join(SecretKey::Verifying.as_string()))?
.write_all(verifying_key.as_bytes())?; // 保存验证密钥
Ok(())
}
/**
*
*/
pub fn get_key(key_type: SecretKey) -> Result<[u8; 32], Box<dyn Error>> {
let path = env::current_dir()?
.join("assets")
.join("key")
.join(key_type.as_string());
let key_bytes = fs::read(path)?; // 读取密钥文件
let mut key = [0u8; 32]; // 固定长度的数组
key.copy_from_slice(&key_bytes[..32]); // 拷贝前32个字节
Ok(key)
}
/**
* JWT
*/
pub fn generate_jwt(claims: CustomClaims, duration: Duration) -> Result<String, Box<dyn Error>> {
let key_bytes = get_key(SecretKey::Signing)?; // 从文件读取私钥
let signing_key = SigningKey::from_bytes(&key_bytes); // 创建SigningKey
let time_options = TimeOptions::new(
Duration::seconds(0), // 设置时间容差为0
Utc::now // 使用当前UTC时间作为时钟函数
); // 设置时间容差为); // 默认时间选项
let claims = jwt_compact::Claims::new(claims) // 创建JWT的有效载荷
.set_duration_and_issuance(&time_options, duration)
.set_not_before(Utc::now()); // 设置不早于时间
let header = Header::empty(); // 创建自定义的头部
let token = Ed25519.token(&header, &claims, &signing_key)?; // 使用Ed25519签名JWT
Ok(token)
}
/**
* JWT并返回自定义声明
*/
pub fn validate_jwt(token: &str) -> Result<CustomClaims, Box<dyn Error>> {
let key_bytes = get_key(SecretKey::Verifying)?; // 从文件读取验证密钥
let verifying = VerifyingKey::from_bytes(&key_bytes)?; // 创建VerifyingKey
let token = UntrustedToken::new(token)?; // 创建未受信任的Token
let token: Token<CustomClaims> = Ed25519.validator(&verifying).validate(&token)?; // 验证Token
let time_options = TimeOptions::new(
Duration::seconds(0), // 设置时间容差为0
Utc::now // 使用当前UTC时间作为时钟函数
); // 设置时间容差为); // 默认时间选项
token.claims()
.validate_expiration(&time_options)? // 验证过期时间
.validate_maturity(&time_options)?; // 验证成熟时间
let claims = token.claims().custom.clone(); // 获取自定义声明
Ok(claims)
}