feat(assets): 更新 Logo 与图片资源,添加数据层服务模块
- 更新 logo.svg/logo-light.svg/logo-white.svg 品牌标识 - 新增 logo-calligraphy.svg 书法体 Logo 变体 - 新增新闻、二维码、微信业务等图片资源 - 删除旧版 JPEG 测试图片 - 新增 CMS 数据层服务模块 (admin-api, auth, cms, crypto, db) - 新增 cases/cross-references/methodology/team 常量数据 - 新增 site-config 站点配置
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import crypto from 'crypto';
|
||||
|
||||
const ALGORITHM = 'aes-256-gcm';
|
||||
const IV_LENGTH = 16;
|
||||
const AUTH_TAG_LENGTH = 16;
|
||||
const SALT = 'novalon-cms-crypto-salt';
|
||||
|
||||
/**
|
||||
* 从 JWT token 派生加密密钥
|
||||
*/
|
||||
function deriveKey(token: string): Buffer {
|
||||
return crypto.pbkdf2Sync(token, SALT, 10000, 32, 'sha256');
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密数据
|
||||
*/
|
||||
export function encrypt(data: unknown, token: string): string {
|
||||
const key = deriveKey(token);
|
||||
const iv = crypto.randomBytes(IV_LENGTH);
|
||||
const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
|
||||
|
||||
const json = JSON.stringify(data);
|
||||
const encrypted = Buffer.concat([
|
||||
cipher.update(json, 'utf8'),
|
||||
cipher.final(),
|
||||
]);
|
||||
const authTag = cipher.getAuthTag();
|
||||
|
||||
// 格式: iv + authTag + encrypted (全部 base64)
|
||||
const combined = Buffer.concat([iv, authTag, encrypted]);
|
||||
return combined.toString('base64');
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密数据
|
||||
*/
|
||||
export function decrypt<T = unknown>(encryptedData: string, token: string): T {
|
||||
const key = deriveKey(token);
|
||||
const combined = Buffer.from(encryptedData, 'base64');
|
||||
|
||||
const iv = combined.subarray(0, IV_LENGTH);
|
||||
const authTag = combined.subarray(IV_LENGTH, IV_LENGTH + AUTH_TAG_LENGTH);
|
||||
const encrypted = combined.subarray(IV_LENGTH + AUTH_TAG_LENGTH);
|
||||
|
||||
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
|
||||
decipher.setAuthTag(authTag);
|
||||
|
||||
const decrypted = Buffer.concat([
|
||||
decipher.update(encrypted),
|
||||
decipher.final(),
|
||||
]);
|
||||
|
||||
return JSON.parse(decrypted.toString('utf8')) as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机 Token(用于前端存储的加密密钥)
|
||||
*/
|
||||
export function generateCryptoToken(): string {
|
||||
return crypto.randomBytes(32).toString('hex');
|
||||
}
|
||||
|
||||
/**
|
||||
* 对敏感字段进行哈希(用于日志脱敏)
|
||||
*/
|
||||
export function hashSensitive(data: string): string {
|
||||
return crypto.createHash('sha256').update(data + SALT).digest('hex').slice(0, 16);
|
||||
}
|
||||
Reference in New Issue
Block a user