3

I use this code to crypt/decrypt string value

var crypto = require('crypto');

function encrypt(text){
    var cipher = crypto.createCipher('aes-256-cbc','secret key');
    var encrypted = cipher.update(text.toString(),'utf8','hex') + cipher.final('hex');
    return encrypted;
}

function decrypt(text){
    var decipher = crypto.createDecipher('aes-256-cbc','secret key');
    var decrypted = decipher.update(text.toString(),'hex','utf8') + decipher.final('utf8');
    return decrypted ;
}

module.exports.encrypt = encrypt;
module.exports.decrypt = decrypt;

When i try to decrypt something that isn't crypted for example decrypt('test') it throw me the following error :

crypto.js:292
  var ret = this._binding.final();
                          ^
TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
    at Decipher.Cipher.final (crypto.js:292:27)

I tryed also to use buffers without sucess and couldn't find any solution over Internet.

The real problem is I use this to decrypt cookie value. If a hacker creates a fake cookie with the value "test" it will crash my program.

Bobby Shark
  • 1,074
  • 2
  • 17
  • 33
  • 1
    But what result did you expect? – Alexey Ten Apr 16 '14 at 14:18
  • The problem is i need to decrypt cookie data. If someone injects a cookie with the value test then i will try to decrypt "test" – Bobby Shark Apr 16 '14 at 14:50
  • Thanks this made the trick, will let this open if there is another solution. – Bobby Shark Apr 16 '14 at 15:13
  • Here are some similar questions and answers: [Decrypting AES256 with node.js returns wrong final block length](https://stackoverflow.com/q/21292142/608639), [Getting error wrong final block length while decrypting AES256](https://stackoverflow.com/q/32038267/608639), [Decrypt file in Node.js encrypted using OpenSSL](https://stackoverflow.com/q/44482151/608639), [How to decipher string in node.js which is encrypted in crypto.js](https://stackoverflow.com/q/28359128/608639), [What's wrong with node.js crypto decipher?](https://stackoverflow.com/q/12219499/608639) – jww Jun 11 '17 at 10:18

2 Answers2

2

The output of AES-CBC (without ciphertext stealing) is always a multiple of 16 bytes (32 hex characters). As you do not provide hexadecimal characters at all ("test") and since the string is not a multiple of 32 hexadecimal characters you will always see an error.

So this:

000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F

would for instance be valid.

So you need to check that what you get is containing the right characters and is of the right length. To make sure that you don't get any padding or content related errors you will need to put a (hexadecimal encoded) HMAC value calculated over the ciphertext at the end. Then first check encoding, length and then the HMAC. If the HMAC is correct you can be assured that the plaintext won't contain any invalid information after decryption.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • ? The real problem is I use this to decrypt cookie value. If a hacker creates a fake cookie with the value "test" it will crash my program. How do I modify my decrypt code so it accepts any strings ? – Bobby Shark Apr 16 '14 at 14:55
  • Test the length of the string and pad it if it's not the right length? Or outright reject it if it's not the right length. But be cautious that you're not inadvertently giving an attacker information by behaving differently if they submit an invalid value. – Jason Apr 16 '14 at 15:17
  • @BobbyShark Ah, now I see, you are creating invalid input on purpose. No problem there, amended answer. You don't want to modify your code to "accept any strings". What you want is that it fails fast in a way that can be controlled before it starts decrypting. – Maarten Bodewes Apr 16 '14 at 21:17
  • @owlstead Well i just want to decrypt anything without having that error. I can decrypt my encrypted cookies but if someone changes the cookie value then the decrypt fonction throw error. And just to say I'm very noob about encryption :) So I guess i have to check for my cookie value for length and also if it's a hex value before sending decryption ? – Bobby Shark Apr 16 '14 at 21:57
  • @Jason Actually I use theses crypted cookies to auth users automaticaly when they connect on the site. One cookie contains the userid and the other a random phrase that changes everytime the auth is granted. After i decrypted the values i check in my db if the random phrase match for that userid. if yes, I update the random phrase both in the db and in the user cookie (that means if a hacker could steal the user cookie, he could login only 1 time. If the user logs in again, the hacker cookie will not work). I could also add IP mask in the db, but with mobile users can connect from everywhere. – Bobby Shark Apr 16 '14 at 22:10
  • Also note [this](http://stackoverflow.com/questions/7761475/node-js-catching-errors-so-script-doesnt-break) little Gem on Node.js. And finally note that I know little to nothing about Node.js :) – Maarten Bodewes Apr 16 '14 at 22:50
  • 1
    @BobbyShark, you've invented a login mechanism that is brittle and insecure. There are many well developed and well defined strategies out there that will be light years beyond what you're proposing here, you should use one of them. For instance, what's to stop an attacker form harvesting multiple "random phrases", and just trying several of them until they get a match? – Jason Apr 17 '14 at 13:04
  • @Jason Well if you could propose me or indicate me a tutorial about one of theses strategies I would be glad. But I don't think hackers can brute force mine. They first have to get the correct crypt key to crypt their random phrase and then find the correct random phrase which is something like 82jaAhadj3fha3Ahadksg"hadaja etc.. – Bobby Shark Apr 18 '14 at 09:53
  • If your "random phrase" is really a cryptographically secure random byte sequence (see [CSPRNG](http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator)), then it's not predictable and you're probably OK, so far as that particular piece goes. I used to have a link to a user session strategy described by one of the guys working on Drupal, if I recall correctly it was something approaching industry best practice, at least a few years ago. I'll have to find it to send to you, or I'll have to look at my implementation of it to give you the details. – Jason Apr 18 '14 at 13:01
0

I also faced the same issue. I had to go through all the comments to check for answer and @Alexey Ten's comment helped me. So in order to make @Alexey Ten's answer more visible below are the changes.

var crypto = require('crypto');

function encrypt(text){
  try{
    var cipher = crypto.createCipher('aes-256-cbc','secret key');
    var encrypted = cipher.update(text.toString(),'utf8','hex') + cipher.final('hex');
    return encrypted;
    } catch(exception) {
      throw exception;
    }
}

function decrypt(text){
try{
    var decipher = crypto.createDecipher('aes-256-cbc','secret key');
    var decrypted = decipher.update(text.toString(),'hex','utf8') + decipher.final('utf8');
    return decrypted ;
  } catch(exception) {
     throw exception;
   }
}
Chetan Gawai
  • 2,361
  • 1
  • 25
  • 36