You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js crypto加解密报EVP_DecryptFinal_ex:bad decrypt错误如何解决

问题原因

你遇到的解密错误核心有两个问题:

  • 加密时使用随机生成的IV,解密时却使用固定全零IV:AES等对称加密算法的CBC模式要求解密时使用的初始化向量(IV)必须和加密时使用的完全一致,你代码里加密阶段调用crypto.randomFill(new Uint8Array(16))生成了随机IV,但解密阶段直接用Buffer.alloc(16, 0)生成了全零的固定IV,二者不匹配直接导致解密失败。
  • 加密接口没有返回加密使用的IV:IV不需要保密,可以和密文一起传输,你当前加密接口只返回了加密后的字符串,没有把本次加密用的IV返回给调用方,解密阶段自然无法获取正确的IV。

修正方案

修改/encrypt接口

将IV转为hex格式和密文一起返回:

app.post("/encrypt", (req, res) => {
  crypto.scrypt(password, "salt", 24, (err, key) => {
    if (err) throw err;
    crypto.randomFill(new Uint8Array(16), (err, iv) => {
      if (err) throw err;
      const cipher = crypto.createCipheriv(algorithm, key, iv);
      let encrypted = "";
      cipher.setEncoding("hex");
      cipher.on("data", (chunk) => (encrypted += chunk));
      cipher.on("end", () => {
        console.log(encrypted);
        // 把iv转成hex和密文一起返回
        res.json({ encrypted, iv: Buffer.from(iv).toString('hex') });
      });
      cipher.write(req.body.payload);
      cipher.end();
    });
  });
});

修改/decrypt接口

接收加密阶段返回的IV,转为Buffer后用于解密:

app.post("/decrypt", (req, res) => {
  const key = crypto.scryptSync(password, "salt", 24);
  // 从请求参数中获取加密时返回的iv,转成Buffer
  const iv = Buffer.from(req.body.iv, 'hex');
  const decipher = crypto.createDecipheriv(algorithm, key, iv);
  let decrypted = "";
  decipher.on("readable", () => {
    while (null !== (chunk = decipher.read())) {
      decrypted += chunk.toString("utf8");
    }
  });
  decipher.on("end", () => {
    console.log(decrypted);
    res.json({ decrypted });
  });
  decipher.write(req.body.payload, "hex");
  decipher.end();
});

额外注意事项
  • 请确认加密和解密阶段使用的algorithm参数完全一致,你这里scrypt生成24字节的密钥,对应的应该是aes-192-cbc算法,不要写错算法名
  • 前端调用解密接口时,需要把加密接口返回的iv和encrypted两个参数都传给解密接口

内容的提问来源于stack exchange,提问作者Amarsh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 04:09:04