Node.js解密AES-256-CBC密文报块长度错误问题求解
问题根因
抛出Error: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length错误的核心原因是代码中对密钥、IV、密文的格式处理存在3个致命问题:
- 错误转换IV格式:AES-256-CBC要求IV为16字节二进制值,原代码将base64解码后的IV转成hex字符串后再截断前16位,得到的是长度16的普通字符串,并非合法的16字节二进制IV。
- 错误处理密钥:SHA256哈希输出本身正好是32字节,完全符合AES-256的密钥长度要求,原代码将哈希结果转成hex字符串后截断前32位,实际得到的是等价于16字节的无效密钥,不满足AES-256的密钥长度要求。
- 多余的字符串替换埋下隐患:
JSON.parse原生支持解析带换行缩进的格式化JSON,不需要提前替换换行符;原代码将全局换行替换为空格的操作,会在base64密文中引入非法空格字符,可能导致密文解码异常。 - 不必要的格式转换:将base64解码后的密文转成hex字符串再传入解密函数属于多余操作,增加了格式转换出错的概率。
正确实现代码
const crypto = require('crypto'); const raw = `{ "iv":"uUwGJgxslfYiahji3+e2jA==", "docMimeType":"text/xml", "doc":"1XLjWZlMMrgcpR6QtfwExQSOOPag1BJZTo1QEkcDrY6PFesWoVw8xrbHFsEYyMVDeemzk+5kBnb3\r\nqBmcUtkSFs7zDsxjYZkkEU9nyq1jXFz99fGylIealw37FPMaK0gviXESRO5AHMs46tpgSQcuWX0Z\r\nV7+mnTvjmaRHi4p1Cvg8aYfDO1aIWWWjAwOTCyopyCwribbGoEdiYDc5pERHpw==" }`; // 直接解析格式化JSON,无需提前处理换行 const data = JSON.parse(raw); // IV处理:base64解码后直接得到16字节合法Buffer const iv = Buffer.from(data.iv, 'base64'); // 密钥处理:明文做SHA256哈希后直接取二进制结果,即为32字节合法AES-256密钥 const key = crypto.createHash('sha256').update('PHilheaLthDuMmyciPHerKeyS').digest(); // 密文处理:先移除所有空白字符(换行、回车、空格等base64非法字符)再解码 const encrypted = Buffer.from(data.doc.replace(/\s+/g, ''), 'base64'); // 执行解密 const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv); let decrypted = decipher.update(encrypted, null, 'utf-8'); decrypted += decipher.final('utf-8'); console.log(decrypted);
运行代码后将输出预期的明文结果:
<eEMPLOYERS ASOF="07-02-2022"><employer pPEN="110474000002" pEmployerName="JOSE A TERAMOTO ODM" pEmployerAddress="ORANBO, PASIG CITY"/></eEMPLOYERS
关于base64中\r\n的处理说明
不少接口返回的base64数据会按固定行宽插入\r\n换行做格式化,这类字符不属于base64合法字符集,解码前只需要通过replace(/\s+/g, '')移除所有空白字符即可,不要将换行替换为其他字符,避免引入非法值导致解码失败。
内容的提问来源于stack exchange,提问作者Jerryco Alaba
相关产品推荐
相关产品推荐

