mongodb AES加密解密错误:'ERR_OSSL_EVP_WRONG_FINAL_BLOCK_LENGTH'

bq3bfh9z  于 2023-10-16  发布在  Go
关注(0)|答案(2)|浏览(269)

我试图使用存储在env函数中的key和iv从mongodb中解密数据来检索数据,但我得到了这个错误:
错误_OSSL_EVP_错误_最终_块_长度

app.get("/recieve", async(req, res) => {
  try {
    const data = await UploadData.find();

    const decryptedData = data.map((item) => {
      const decryptedFullName = decryptData(item.fullname, secretKey);
      const decryptedCatName = decryptData(item.catName, secretKey);
      const decryptedEmail = decryptData(item.email, secretKey);
      const decryptedContact = decryptData(item.contact, secretKey);
      const decryptedLocation = decryptData(item.location, secretKey);

      return {
        ...item.toObject(),
        fullname: decryptedFullName,
        catName: decryptedCatName,
        email: decryptedEmail,
        contact: decryptedContact,
        location: decryptedLocation,
      };
    });
    res.json(decryptedData);
  } catch (error) {
    console.error("Error fetching data:", error);
    res.status(500).json({
      error: "Internal server error"
    });
  }
});

解密数据的函数:

function decryptData(encryptedData, key) {
  try {
    const buff = Buffer.from(encryptedData, "base64");
    encryptedData = buff.toString("utf-8");
    var decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
    return (
      decipher.update(encryptedData, "base64", "utf8") +
      decipher.final("utf8")
    );
  } catch (error) {
    console.log("Error decrypting data:", error);
    return null;
  }
}

数据是这样加密的:

function encryptData(data, key, iv) {
  const keyBuffer = Buffer.from(key, "hex");
  const cipher = crypto.createCipheriv("aes-256-cbc", keyBuffer, iv);

  let encryptedData = cipher.update(data, "utf8", "base64") + cipher.final("base64");
  return encryptedData;
}
v440hwme

v440hwme1#

你试图在这里进行的转换:

encryptedData = Buffer.from(encryptedData, "base64").toString("utf-8")

破坏您的数据(不可逆)。将Base64编码的数据直接传递给update(),参见此处。如果这不起作用,则您的数据不一致(错误的密钥,错误的IV,损坏的密文等)此答案的功劳属于Topaco
正确的方法应该是这样的:

const crypto = require("crypto");

const key = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
const keyBuffer = Buffer.from(key, "hex");
const iv = Buffer.from("202122232425262728292a2b2c2d2e2f", "hex");
const data = "The quick brown fox jumps over the lazy dog";

// Encryption
const cipher = crypto.createCipheriv("aes-256-cbc", keyBuffer, iv);
var encryptedData = cipher.update(data, "utf8", "base64") + cipher.final("base64");
console.log(encryptedData);

// Decryption
const decipher = crypto.createDecipheriv("aes-256-cbc", keyBuffer, iv);
//encryptedData = Buffer.from(encryptedData, "base64").toString("utf-8"); // this line corrupts your data
const decryptedData = decipher.update(encryptedData, "base64", "utf8") + decipher.final("utf8");
console.log(decryptedData);
nzk0hqpo

nzk0hqpo2#

如果我没记错的话,这个错误意味着它期望最后一个块被填充,但它没有:
From:https://www.openssl.org/docs/man1.0.2/man3/EVP_CIPHER_CTX_set_padding.html
如果数据% 16的长度不等于0(数据不是块大小16字节的倍数),则块密码(CBC)需要填充:

int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding);

如果启用了填充(默认值),则EVP_EncryptFinal_ex()加密“最终”数据,即保留在部分块中的任何数据。它使用标准的块填充(aka PKCS padding)。加密后的最终数据被写入输出,其应该具有足够的空间用于一个密码块。写入的字节数放在outl中。调用此函数后,加密操作完成,不应再调用EVP_EncryptUpdate()。
如果填充被禁用,则EVP_EncryptFinal_ex()将不会加密任何更多的数据,并且如果有任何数据保留在部分块中,它将返回错误:即如果总数据长度不是块大小的倍数。

相关问题