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) } }