78 lines
2.1 KiB
TypeScript
78 lines
2.1 KiB
TypeScript
import CryptoJS from 'crypto-js'
|
||
|
||
/**
|
||
* HiAesUtil - AES-256-CBC 加密工具类
|
||
* 逻辑与 Dart 版本保持 100% 同步
|
||
*/
|
||
export class HiAesUtil {
|
||
/**
|
||
* 生成 32 字节密钥 (SHA-256)
|
||
*/
|
||
static _generateKey(keyStr) {
|
||
return CryptoJS.SHA256(keyStr)
|
||
}
|
||
|
||
/**
|
||
* 生成 16 字节 IV
|
||
* 逻辑: SHA-256(MD5(nonce) + keyStr) -> 取前16字节
|
||
*/
|
||
static _generateIv(nonce, keyStr) {
|
||
// 1. MD5 处理 nonce
|
||
const md5Hash = CryptoJS.MD5(nonce)
|
||
// 2. 转为 16 进制字符串
|
||
const md5Hex = md5Hash.toString(CryptoJS.enc.Hex)
|
||
// 3. 拼接 md5Hex + keyStr 并做 SHA-256
|
||
const finalHash = CryptoJS.SHA256(md5Hex + keyStr)
|
||
|
||
// 4. 重要:截取前 16 字节 (128位)
|
||
// CryptoJS 的 WordArray 由 32 位整数组成,16 字节即前 4 个 words
|
||
const iv = CryptoJS.lib.WordArray.create(finalHash.words.slice(0, 4), 16)
|
||
return iv
|
||
}
|
||
|
||
/**
|
||
* 加密方法
|
||
* @param {string} plainText - 明文
|
||
* @param {string} keyStr - 密钥
|
||
*/
|
||
static encryptData(plainText, keyStr) {
|
||
// 生成 ISO8601 时间戳 (与 Dart DateTime.now().toIso8601String() 对应)
|
||
// Dart: 2025-12-30T21:05:06.075850 (no Z, 6 decimal places)
|
||
const now = new Date()
|
||
const nonce = now.toISOString().replace('Z', '') + '000'
|
||
|
||
const key = this._generateKey(keyStr)
|
||
const iv = this._generateIv(nonce, keyStr)
|
||
|
||
const encrypted = CryptoJS.AES.encrypt(plainText, key, {
|
||
iv: iv,
|
||
mode: CryptoJS.mode.CBC,
|
||
padding: CryptoJS.pad.Pkcs7,
|
||
})
|
||
|
||
return {
|
||
data: encrypted.toString(), // Base64 字符串
|
||
time: nonce,
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 解密方法
|
||
* @param {string} encryptedData - Base64 加密字符串
|
||
* @param {string} nonce - 时间戳
|
||
* @param {string} keyStr - 密钥
|
||
*/
|
||
static decryptData(encryptedData, nonce, keyStr) {
|
||
const key = this._generateKey(keyStr)
|
||
const iv = this._generateIv(nonce, keyStr)
|
||
|
||
const decrypted = CryptoJS.AES.decrypt(encryptedData, key, {
|
||
iv: iv,
|
||
mode: CryptoJS.mode.CBC,
|
||
padding: CryptoJS.pad.Pkcs7,
|
||
})
|
||
|
||
return decrypted.toString(CryptoJS.enc.Utf8)
|
||
}
|
||
}
|