Node.js中decipher.final()抛出‘wrong final block length’错误
解决解密时"wrong final block length"错误的问题
你遇到的ERR_OSSL_EVP_WRONG_FINAL_BLOCK_LENGTH错误,核心原因大概率是加密数据写入文件时的格式损坏,或者读取解析环节的编码不匹配——毕竟你直接传文本能正常解密,说明加密解密的核心逻辑是没问题的,问题出在文件的读写流程上。
可能的问题点分析
- 加密后的数据写入文件时,没有正确将二进制加密结果转为hex字符串保存,直接用utf-8编码写入Buffer导致二进制数据损坏
- JSON序列化或写入文件时,对hex字符串做了不必要的转义,读取解析后hex格式变形
- 解密读取文件时未明确指定编码,导致JSON解析出的
encryptedData字符串异常
针对性解决方案
1. 先修正加密写入逻辑(最关键!)
确保你加密后,是把iv和encryptedData都转为hex字符串存入JSON,再以utf-8编码写入文件。正确的加密逻辑示例:
function encrypt(plainText, outputFile) { const iv = crypto.randomBytes(16); // 以AES-256-CBC为例,需要16字节IV const cipher = crypto.createCipheriv(algorithm, Buffer.from(key), iv); let encrypted = cipher.update(plainText, 'utf8'); encrypted = Buffer.concat([encrypted, cipher.final()]); // 把二进制数据转为hex字符串,避免写入时损坏 const saveData = { iv: iv.toString('hex'), encryptedData: encrypted.toString('hex') }; // 明确用utf-8编码写入JSON字符串 fs.writeFileSync(outputFile, JSON.stringify(saveData), 'utf8'); }
如果之前你是直接把encrypted这个Buffer写入文件(没有转hex),或者用了错误的编码,那读取后解析出的内容肯定和原加密数据不匹配,必然触发解密块长度错误。
2. 修复解密函数的细节问题
你的解密函数里有变量重复声明的小问题,同时建议明确指定文件读取编码:
function decrypt(file) { // 明确以utf8编码读取文件,避免默认Buffer读取的编码问题 const data = JSON.parse(fs.readFileSync(file, 'utf8')); const iv = Buffer.from(data.iv, 'hex'); const encryptedText = Buffer.from(data.encryptedData, 'hex'); const decipher = crypto.createDecipheriv( algorithm, Buffer.from(key), iv ); let decrypted = decipher.update(encryptedText); // 去掉重复的let声明,避免变量覆盖 decrypted = Buffer.concat([decrypted, decipher.final()]); // 明确转utf8字符串,避免默认编码导致的乱码 return decrypted.toString('utf8'); }
3. 验证加密文件的完整性
手动打开你的file.json.enc文件,检查encryptedData字段是否是一串连续的十六进制字符(只有0-9、a-f/A-F),没有乱码或转义字符。如果有乱码,说明写入时的编码错误,回到加密步骤修正即可。
4. 确认算法与密钥的一致性
最后要确保解密时使用的algorithm(比如'aes-256-cbc')和密钥key,和加密时完全一致——密钥长度也要匹配,比如AES-256需要32字节的密钥,长度不匹配也会触发类似的块错误。
测试验证
按照上面的步骤修正后,可以用一段简单的文本测试:
// 测试加密 encrypt('测试解密功能', './test.enc'); // 测试解密 console.log(decrypt('./test.enc'));
如果测试正常,说明之前的问题确实出在文件读写的编码或格式环节。
内容的提问来源于stack exchange,提问作者Chandu




