Node.js crypto aes-256-cbc解密报错:encoding参数无效问题排查
问题原因及修复方案
错误根源
1. 加密时的Buffer转换逻辑错误
原加密代码将cipher输出的hex字符串以默认的utf8编码转成Buffer,这会破坏原始加密数据的二进制结构。hex字符串的每个字符对应4位二进制,按utf8解析时,部分字符会被视为多字节字符,导致最终生成的Base64字符串还原后,hex字符串长度可能为奇数(如383),而hex编码要求字符串长度必须为偶数,因此触发解密错误。
2. 密钥和IV长度不符合AES-256-CBC要求
原代码通过digest('hex')后截取字符串的方式生成key和iv,得到的key仅为16字节(32个hex字符),但AES-256-CBC要求key必须是32字节(256位),这会导致加密算法实际使用的密钥长度不匹配,存在安全隐患。
修复后的代码
const crypto = require("crypto"); // 修正key和iv的生成:直接取哈希后的Buffer前N字节,满足AES-256-CBC的要求 const key = crypto .createHash('sha512') .update(process.env.AES_SECRET_KEY) .digest() // 得到64字节的Buffer .subarray(0, 32); // 取前32字节作为256位密钥 const encryptionIV = crypto .createHash('sha512') .update(process.env.AES_SECRET_IV) .digest() .subarray(0, 16); // 取前16字节作为IV const method = 'aes-256-cbc' // 加密数据:直接操作Buffer,避免hex字符串转码错误 exports.encryptData = (data) => { try { const cipher = crypto.createCipheriv(method, key, encryptionIV); // 拼接cipher输出的Buffer,直接转Base64 const encryptedBuffer = Buffer.concat([ cipher.update(data, 'utf8'), cipher.final() ]); return encryptedBuffer.toString('base64'); } catch (error) { return undefined; } } // 解密数据:对应加密逻辑,直接解析Base64为Buffer后解密 exports.decryptData = (encryptedData) => { try { const buff = Buffer.from(encryptedData, 'base64'); const decipher = crypto.createDecipheriv(method, key, encryptionIV); // 拼接decipher输出的Buffer,转utf8字符串 const decryptedBuffer = Buffer.concat([ decipher.update(buff), decipher.final() ]); return decryptedBuffer.toString('utf8'); } catch (error) { return undefined; } }
额外说明
- 直接操作Buffer的方式比hex字符串中转更高效,且避免了编码转换带来的错误。
- 确保
process.env.AES_SECRET_KEY和process.env.AES_SECRET_IV是足够复杂的随机字符串,避免使用弱密钥。
内容的提问来源于stack exchange,提问作者Burak Turna
相关产品推荐
相关产品推荐

