Swarnava Sarkar Swarnava Sarkar - 3 months ago 13
Node.js Question

Node Crypto AES decrypt issue

We have been provided with an encrypted text and a passphrase. Along with that they have informed that the text has been encrypted using AES-128

Encrypted Text - 5vCGQXtdj7GZtwwhwVOquSyR/qvs95ojBsmOf9DX6T31Y2yTIvjXYHf6gd8icDaY
Passphrase/password - FX4DqkZCb4KI6BWF

Expected O/P - e23f95c7-79c2-4c6f-9408-411bcfaf3665

Now when I decrypt online from http://aesencryption.net/
It does generate the Guid, However, it does not work with any other online tool.

Also, I need to implement the same in Node Js.
I have used the code mentioned below, but still that does not work and thus generate unwanted data.

var aesDecrypt = (text, password, bit) => {
debugger;
var crypto = require('crypto');
var decipher = crypto.createDecipher('aes-' + bit + '-cbc', password);
decipher.setAutoPadding(false);
var plaintext = decipher.update(text, 'base64', 'utf8');
var token = plaintext.toString();
return token;
}

Answer

There are a few issues here:

  • CBC mode is being used but the text was encrypted using ECB mode (I guessed this by looking at the default mode in the code examples on the site you linked to).

  • crypto.createDecipher()'s password parameter is not what you think it is. It's actually just a value that gets hashed with MD5 to generate the needed decryption key. Instead what you need is crypto.createDecipheriv() which accepts a key and IV. In the case of ECB, IVs are not used, so you can just pass an empty Buffer for that parameter.

  • You aren't calling decipher.final() to get any potentially remaining output. Also IIRC if you have multi-byte characters in the text, calling decipher.update(text, 'base64', 'utf8') could lead to decrypted data corruption if the character's bytes are split across calls to .update() and/or .final().

  • Calling .toString() on a string is not useful.

With all of that in mind, here is code that will work for your example inputs:

var aesDecrypt = (text, password, bit) => {
  var crypto = require('crypto');
  var decipher = crypto.createDecipheriv('aes-' + bit + '-ecb', password, Buffer.alloc(0));
  decipher.setAutoPadding(false);
  return Buffer.concat([
    decipher.update(text, 'base64'),
    decipher.final()
  ]).toString();
}

console.log(aesDecrypt(
  '5vCGQXtdj7GZtwwhwVOquSyR/qvs95ojBsmOf9DX6T31Y2yTIvjXYHf6gd8icDaY',
  'FX4DqkZCb4KI6BWF',
  128
));