skip to Main Content

I am trying to decrypt data from mongodb using key and iv which was stored in env function to retrieve data, but I am getting this error:

ERR_OSSL_EVP_WRONG_FINAL_BLOCK_LENGTH

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 to decrypt data:

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;
  }
}

The data is being encrypted like this:

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;
}

2

Answers


  1. If I recall correctly, that error means that it was expecting the last block to be padded but it wasn’t:

    From: https://www.openssl.org/docs/man1.0.2/man3/EVP_CIPHER_CTX_set_padding.html

    If the length of the data % 16 is not equal to 0 (the data is not a multiple of block size 16 bytes) block ciphers (CBC) require padding:

    int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding);
    

    If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts the "final" data, that is any data that remains in a partial block. It uses standard block padding (aka PKCS padding). The encrypted final data is written to out which should have sufficient space for one cipher block. The number of bytes written is placed in outl. After this function is called the encryption operation is finished and no further calls to EVP_EncryptUpdate() should be made.

    If padding is disabled then EVP_EncryptFinal_ex() will not encrypt any more data and it will return an error if any data remains in a partial block: that is if the total data length is not a multiple of the block size.

    Login or Signup to reply.
  2. This conversion you’re trying to here:

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

    damages your data (irreversibly). Pass the Base64 encoded data encryptedData directly to update(), see here. If this doesn’t work your data is inconsistent (wrong key, wrong IV, corrupted ciphertext etc.)
    The credit to this answer belongs to Topaco

    The correct method would be like this:

    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);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search