import * as CryptoJS from 'crypto-js' const SIGN_BYTES_LEN = 16 const CRYPTO_SECRET_KEY_MAP = { local: 'asdb2l0jskjft1q314f3ffjy71k9shj6', development: 'asdb2l0jskjft1q314f3ffjy71k9shj6', pre: 'asdb2l0jskjft1q314f3ffjy71k9shj6', production: 'asdb2l0jskjft1q314f3ffjy71k9shj6', } as Record export class AESUtils { private secretKey: string constructor(env?: string) { // Default to production key if env is missing, matching the logic this.secretKey = CRYPTO_SECRET_KEY_MAP[env || 'production'] } private get getSecretKey() { return CryptoJS.enc.Utf8.parse(this.secretKey) } decryptAES_CBC(ciphertext: string): string { const secretKey = this.getSecretKey try { // 将 URL 安全的 Base64 编码的密文解码 const ciphertextBytes = CryptoJS.enc.Base64.parse( ciphertext.replace(/-/g, '+').replace(/_/g, '/'), ) // 从密文中提取 IV(前 16 字节) const iv = ciphertextBytes.clone() iv.sigBytes = SIGN_BYTES_LEN iv.clamp() // 从密文中提取实际的加密数据 const encryptedContent = ciphertextBytes.clone() encryptedContent.words.splice(0, SIGN_BYTES_LEN / 4) // 移除前 16 字节(IV) encryptedContent.sigBytes -= SIGN_BYTES_LEN // 执行解密 const decrypted = CryptoJS.AES.decrypt( { ciphertext: encryptedContent } as any, secretKey, { iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, }, ) // 将解密结果转换为 UTF-8 字符串 return decrypted.toString(CryptoJS.enc.Utf8) } catch (e) { console.error(e) throw new Error('解密失败') } } // Included purely for completeness if needed later encryptAES_CBC(data: string): string { const secretKey = this.getSecretKey try { const iv = CryptoJS.lib.WordArray.random(SIGN_BYTES_LEN) const encrypted = CryptoJS.AES.encrypt(data, secretKey, { iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, }) // 将 IV 和密文连接,然后进行 Base64 编码 const result = iv.concat(encrypted.ciphertext) return CryptoJS.enc.Base64.stringify(result) } catch (e) { console.error(e) throw new Error('加密失败') } } }