I'm trying to implement encryption and decryption method on messages for a web based chat app. In this chat I'm encrypting the messages in my frontend and then storing these messages to my database. Now I need to fetch these encrypted messages from the database and decrypt them. But I'm Getting this error:
Error decrypting data: Error: Authentication tag does not match tag length.
,
This is the code I am using to encrypt and decrypt the data.
import forge from 'node-forge';
// Convert hex to ByteStringBuffer
const hexToBytes = (hex) => forge.util.createBuffer(forge.util.hexToBytes(hex));
// Function to encrypt data with a session key in hex format
export const encryptDataWithSessionKey = (data, sessionKeyHex) => {
console.log('data during encryption: ', data);
try {
const sessionKey = hexToBytes(sessionKeyHex);
// Generate a random IV (Initialization Vector)
const iv = forge.random.getBytesSync(12); // 96 bits IV for GCM
console.log('iv during encryption: ', iv);
const dataBytes = forge.util.encodeUtf8(data);
// Encrypt the data using the session key and IV
const cipher = forge.cipher.createCipher('AES-GCM', sessionKey);
console.log('cipher during encryption: ', cipher);
cipher.start({ iv, tagLength: 128 });
cipher.update(forge.util.createBuffer(dataBytes));
cipher.finish();
// Get the encrypted bytes along with the IV
const encrypted = cipher.output.getBytes();
console.log('encrypted during encryption: ', encrypted, encrypted.length);
// Convert the encrypted bytes and IV to a Base64-encoded string
const encryptedBase64 = forge.util.encode64(iv + encrypted);
console.log('encryptedBase64 during encryption: ', encryptedBase64, encryptedBase64.length);
return encryptedBase64;
} catch (error) {
console.error('Error encrypting data:', error);
throw error;
}
};
// Function to decrypt data with a session key in hex format
export const decryptDataWithSessionKey = (encryptedData, sessionKeyHex) => {
console.log('encryptedData during decryption: ', encryptedData);
try {
const sessionKey = hexToBytes(sessionKeyHex);
const encryptedBytesWithIV = forge.util.decode64(encryptedData);
// Extract the IV and encrypted data
const iv = encryptedBytesWithIV.slice(0, 12);
console.log('iv during decryption: ', iv);
const encryptedBytes = encryptedBytesWithIV.slice(12);
console.log('encryptedBytes during decryption: ', encryptedBytes, encryptedBytes.length);
// Decrypt the data using the session key and IV
const decipher = forge.cipher.createDecipher('AES-GCM', sessionKey);
console.log('decipher during decryption: ', decipher);
console.log(1);
decipher.start({ iv, tagLength: 128 });
decipher.update(forge.util.createBuffer(encryptedBytes));
console.log(2);
decipher.finish();
console.log(3);
// Get the decrypted bytes
const decrypted = decipher.output.getBytes();
// Convert the decrypted bytes to a UTF-8 string
const decryptedData = forge.util.decodeUtf8(decrypted);
return decryptedData;
} catch (error) {
console.error('Error decrypting data:', error);
throw error;
}
};
I have checked all the values which are being passed in here like data
, sessionKeyHex
and encryptedData
. I even have checked all the internal values like iv
and cipherText
and encrypted
all are the same during encryption and decryption. Even I have defined tagLength
on my own both times during encryption and decryption to make sure that tagLength
does not change. I am just confirming that all the data is correctly passing in all manner.
Now the error I'm talking about is coming during this line
decipher.start({ iv, tagLength: 128 });
.
In console
I am getting output 1
but I am not getting the values after that line. Instead I am getting the error
Error decrypting data: Error: Authentication tag does not match tag length.
.
I know that this authentication tag automatically added to encrypted message after running cipher.finish()
but I don't think that in my code is attaching that's why I am getting the error.
So what am I performing wrong in this code due to which I am getting this error. Any helps pls
In your code, the authentication tag is not taken into account. To fix this, the following changes are required (s. also the GCM example in the documentation):
encryptDataWithSessionKey()
:const encryptedBase64 = forge.util.encode64(iv + encrypted + cipher.mode.tag.data); // Fix 1: append tag
decryptDataWithSessionKey()
:const encryptedBytesWithIVandTag = forge.util.decode64(encryptedData);
const iv = encryptedBytesWithIVandTag.slice(0, 12);
const encryptedBytes = encryptedBytesWithIVandTag.slice(12, -16); // Fix 2: consider tag
const tag = encryptedBytesWithIVandTag.slice(-16); // Fix 3: separate tag
...
decipher.start({ iv, tag: tag }); // Fix 4: specify tag