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
相关产品推荐
相关产品推荐

