You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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. 先修正加密写入逻辑(最关键!)

确保你加密后,是把ivencryptedData都转为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

火山引擎 最新活动