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
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:
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.
This conversion you’re trying to here:
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: