chore: mqsrv backend
This commit is contained in:
64
src/utils/encryption.ts
Normal file
64
src/utils/encryption.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import crypto from 'crypto';
|
||||
|
||||
const ALGORITHM = 'aes-256-cbc';
|
||||
const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY || '0123456789abcdef0123456789abcdef';
|
||||
|
||||
export interface EncryptedData {
|
||||
encrypted: boolean;
|
||||
iv: string;
|
||||
data: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* AES 加密
|
||||
*/
|
||||
export function encrypt(text: string): EncryptedData {
|
||||
const iv = crypto.randomBytes(16);
|
||||
const key = Buffer.from(ENCRYPTION_KEY, 'utf-8');
|
||||
|
||||
const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
|
||||
let encrypted = cipher.update(text, 'utf-8', 'hex');
|
||||
encrypted += cipher.final('hex');
|
||||
|
||||
return {
|
||||
encrypted: true,
|
||||
iv: iv.toString('hex'),
|
||||
data: encrypted,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* AES 解密
|
||||
*/
|
||||
export function decrypt(ivHex: string, dataHex: string): string {
|
||||
const iv = Buffer.from(ivHex, 'hex');
|
||||
const encryptedData = Buffer.from(dataHex, 'hex');
|
||||
const key = Buffer.from(ENCRYPTION_KEY, 'utf-8');
|
||||
|
||||
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
|
||||
let decrypted = decipher.update(encryptedData, undefined, 'utf-8');
|
||||
decrypted += decipher.final('utf-8');
|
||||
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* 密码哈希
|
||||
*/
|
||||
export function hashPassword(password: string): string {
|
||||
return crypto.createHash('sha256').update(password).digest('hex');
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机字符串
|
||||
*/
|
||||
export function randomString(length: number = 32): string {
|
||||
return crypto.randomBytes(length).toString('hex').slice(0, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成设备哈希
|
||||
*/
|
||||
export function generateDeviceHash(data: string): string {
|
||||
return crypto.createHash('sha256').update(data).digest('hex').slice(0, 64);
|
||||
}
|
||||
47
src/utils/jwt.ts
Normal file
47
src/utils/jwt.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
|
||||
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '7d';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const jwtSign = jwt.sign as any;
|
||||
|
||||
export interface JwtPayload {
|
||||
userId: string;
|
||||
username: string;
|
||||
email: string;
|
||||
isVip: boolean;
|
||||
vipLevel: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 JWT Token
|
||||
*/
|
||||
export function generateToken(payload: JwtPayload): string {
|
||||
return jwtSign(payload, JWT_SECRET, { expiresIn: JWT_EXPIRES_IN });
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证 JWT Token
|
||||
*/
|
||||
export function verifyToken(token: string): JwtPayload | null {
|
||||
try {
|
||||
return jwt.verify(token, JWT_SECRET) as JwtPayload;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从请求头提取 Token
|
||||
*/
|
||||
export function extractToken(authHeader?: string): string | null {
|
||||
if (!authHeader) return null;
|
||||
|
||||
const parts = authHeader.split(' ');
|
||||
if (parts.length !== 2 || parts[0] !== 'Bearer') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parts[1];
|
||||
}
|
||||
Reference in New Issue
Block a user