I don't have a node.js application running at hand right now, but I believe you need to take the following steps:
- Laravel encrypted string
- base64 decode
- JSON.parse()
- Get the IV
- base64 decode that.
- Done
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
I am trying to decrypt a string that was previously encrypted by Laravel and stored in a DB from a Node.JS application.
I am having a problem with the IV. I have retrieved the encrypted string from the DB, base64 decoded this and JSON parsed the result to get an object with the value, IV and MAC. However, the IV value is not 16 characters long, and running another base 64 decode on this results in garbage text. I'm not sure what step I need to take to obtain a valid IV, so I can pass this to the Node.js decrypt (along with the app key and value for decryption) in order to complete the decryption.
I finally cracked it!
It was a matter of ensuring that the encoding parameters passed to crypto were explicit and accurate - it was treating some strings as buffers and vice versa. Below is my full function in case anyone wants it. There is an app variable which holds the encryption key and also provides a caching layer for previously decrypted values. This could be improved by verifying the MAC code as Laravel itself does when decrypting.
If you are using the app key directly from Laravel, please also take note of @georgeinggs comment
var crypto = require('crypto');
var Base64 = require('js-base64').Base64;
var serialize = require('php-serialize');
/** Decrypts Laravel encrypted data
*
* @type {Function}
* @param {string} app - Express app instance, must have encryptionKey and decryptionCache defined on it during init
* @param {function} data - Base64 encoded encryption string as created by Laravel
* @access public
*/
function decrypt(app, data) {
// If no data - return blank string
if (data !== "") {
// Check localised cache to save time
if (!app.decryptionCache[data]) {
try {
// Decode and parse required properties
var b64 = Base64.decode(data);
var json = JSON.parse(b64);
var iv = Buffer.from(json.iv, "base64");
var value = Buffer.from(json.value, "base64");
// Create decipher
var decipher = crypto.createDecipheriv("aes-256-cbc", app.encryptionKey, iv);
// Decrypt
var decrypted = decipher.update(value, 'binary', 'utf8');
decrypted += decipher.final('utf8');
// Unserialize
unserialized = serialize.unserialize(decrypted);
// Store in cache
app.decryptionCache[data] = unserialized;
return unserialized;
}
catch(e) {
console.log(e);
return "";
}
}
else {
// Use cached value
return app.decryptionCache[data];
}
}
else {
return "";
}
}
module.exports = {
decrypt: decrypt
};
Please or to participate in this conversation.