3

I'm facing exactly the same problem mentioned in this thread while encrypting and decrypting using AES.

crypto.js:202
var ret = this._handle.final(); ^ Error: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
at Error (native)
at Decipher.Cipher.final (crypto.js:202:26)

These are my encrypt and decrypt functions:

var config = {
cryptkey: crypto.createHash('sha256').update('Nixnogen').digest(),
iv: "a2xhcgAAAAAAAAAA"
};

function encryptText(text){
    console.log(config.cryptkey);
        var cipher = crypto.createCipheriv('aes-256-cbc', config.cryptkey, config.iv);
        var crypted = cipher.update(text,'utf8','binary');
        crypted += cipher.final('binary');
    crypted = new Buffer(crypted, 'binary').toString('base64');
        return crypted;
}

function decryptText(text){
    console.log(config.cryptkey);
        if (text === null || typeof text === 'undefined' || text === '') {return text;};
    text = new Buffer(text, 'base64').toString('binary');
        var decipher = crypto.createDecipheriv('aes-256-cbc', config.cryptkey, config.iv);
        var dec = decipher.update(text,'binary','utf8');
        dec += decipher.final('utf8');
        return dec;
}

I've set "node": ">=0.10.0" in my package.json.

Can anyone tell me how to fix it? I have tried solutions mentioned in the thread but none of them are working for me.

Updates:

I've tried solutions mentioned in the thread but none of them are working for me. I think there might be a different solution for this and hence, rather than polluting the existing thread, decided to create a new one. Also, if I continue this on the existing thread it might confuse future candidates for the right solution.

Update 2:

For the second solution mentioned in the thread, I have the following code, but it is also giving me the same error:

function encryptText(text){
    console.log(config.cryptkey);
        var cipher = crypto.createCipheriv('aes-256-cbc', config.cryptkey, config.iv);
    return Buffer.concat([
        cipher.update(text),
        cipher.final()
    ]);
}

function decryptText(text){
    console.log(config.cryptkey);
        if (text === null || typeof text === 'undefined' || text === '') {return text;};
        var decipher = crypto.createDecipheriv('aes-256-cbc', config.cryptkey, config.iv);
    return Buffer.concat([
        decipher.update(text),
        decipher.final()
    ]);
}

Also, I'm using these functions as getters and setters for a field in my mongodb database using mongoose. I don't think doing so will cause any issues, but I still thought it would be a good idea to mention this.

Update 3:

I'm trying to encrypt a Facebook access token and decrypt an encrypted Facebook access token.

To reproduce the error, you can try encrypting this token:

ASDFGHJKLO0cBACJDJoc25hkZAzcOfxhTBVpHRva4hnflYEwAHshZCi2qMihYXpS2fIDGsqAcAlfHLLo273OWImZAfo9TMYZCbuZABJkzPoo4HZA8HRJVCRACe6IunmBSMAEgGVv8KCLKIbL6Gf7HJy9PplEni2iJ06VoZBv0fKXUvkp1k7gWYMva1ZAyBsWiDiKChjq3Yh1ZCdWWEDRFGTHYJ

Encryption will work fine and you will get an encrypted string.

Now try decrypting the encrypted string which you got in the previous step. You will get the error.

Adaline Simonian
  • 4,596
  • 2
  • 24
  • 35
dark_shadow
  • 3,503
  • 11
  • 56
  • 81
  • The question you've pointed to has several solutions, both of which are pretty different from the code you have listed. Did you actually try those solutions? From what you've given us so far, you appear to be re-asking the same question without actually having tried to work through a solution based on the solution over there. – loganfsmyth Aug 16 '15 at 19:50
  • @loganfsmyth: I have tried possible solutions, as you can see I'm specifically mentioning the utf8 and binary format in the functions as mentioned in one of the solutions...This is the exact same code except valiables name has been changed...Why do you see this code is different from the one mentioned in the thread ? – dark_shadow Aug 17 '15 at 03:13
  • @Qiu: I have already given reference to the thread which you are mentioning. Though the issue faced is similar but their solution is not working for me which means there will be a different solution for this one and that's the reason I have created a separate thread rather than polluting the existing thread – dark_shadow Aug 17 '15 at 03:15
  • @loganfsmyth: I have tried your solution also mentioned in the thread. See my update 2. It is also not working. – dark_shadow Aug 17 '15 at 03:48
  • Can you give more of a reproducible case? Exactly what node version are you using? What is the data you are trying to encrypt? Running your sample code on a short string works fine for me. – loganfsmyth Aug 17 '15 at 04:07
  • Yeah sure...I'm using node 0.12.4. I'm using facebook access token to encrypt and decrypt before storing/reading in mongo db..Can you try with this token: CAhfhfhose0cBAJY0SuQjmlQaXUqv78ffdlQwkP8CbZBUH5z0SiNpagpNEDa1sxh1ZCOAIueZB7ckfJBZCZCczrdCzMNmBZACzKT7lKVwmfMcltUaUC115okWSC7274gjeHbTRP5Fe4ZCJhCczFGIdHydB4ZCNn6L1uFsuBysUWqPyr6gKVuR0ZAqVm5OHbExrb5NPJa1ea26lWWWWWW...you can get a token using this https://developers.facebook.com/tools/explorer – dark_shadow Aug 17 '15 at 07:03
  • Note that the characters `+` and `/` are suspiciously missing from above base64 string. I think you may lose data while storing / retrieving from the DB. – Maarten Bodewes Aug 17 '15 at 16:15
  • Please update the question with *exactly* what code you are running to get that error. I get that if I try to decrypt the access token, for example. What is the data you are decrypting? – loganfsmyth Aug 17 '15 at 16:37
  • @MaartenBodewes: The token I gave is a raw token without any encryption. – dark_shadow Aug 17 '15 at 18:22
  • @loganfsmyth: See my update in the question – dark_shadow Aug 17 '15 at 18:23
  • Could you try and recreate the value of `crypted` *right after* encryption in hexadecimals and compare that with `text` right before decryption, also in hexadecimals? Do they match? Please use the *first* code fragments. – Maarten Bodewes Aug 17 '15 at 18:36
  • Yeah, you say `you will get an encrypted string` but unless that string is Hex, your issue is almost certainly around how you convert the data back and forth to a string. Encrypted data is binary, it should not be treated as a string. That's the point solved by the code in update #2 addresses. – loganfsmyth Aug 17 '15 at 18:38
  • @loganfsmyth: so you mean there is some issue happening while storing the encrypted hexadecimal string in dB? If that is the issue then should I change mongoose object type to something other than string ?? Please correct me if I have misunderstood the things – dark_shadow Aug 17 '15 at 19:29
  • 1
    Where is there a hexadecimal string? Nothing in your code convert it to hex, that's part of my point. I need you to produce a 100% reproducible example of this in code. I've asked several times for a solid code example and you keep giving written directions that are only reproducible if I play around with it. If you expect people to answer your question, you need to give us as much help as you can. What is some exact JS that I can run to reproduce this issue 100%? No mongoose, nothing extra, just simple JS. – loganfsmyth Aug 17 '15 at 20:56
  • Found the issue. When we update in mongodb using mongoose, it wasn't using setters and during fetching it was using getters for decrypting the text. This link helped me to solve the issue http://stackoverflow.com/questions/18837173/mongoose-setters-only-get-called-when-create-a-new-doc – dark_shadow Aug 19 '15 at 09:19
  • Here are some similar questions and answers: [Decrypting AES256 with node.js returns wrong final block length](https://stackoverflow.com/q/21292142/608639), [Nodejs decrypt using crypto error wrong final block length](https://stackoverflow.com/q/23111388/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:19

1 Answers1

6

This question is two years old at the time of this writing, but it has quite a few views, so I hope this answer will still prove useful to someone who might come across it.

The problem here is that encryptText works fine, but it's not returning a string. It's returning a Buffer. decryptText is expecting a string, not a Buffer, so it tries to read it as though it were a Buffer and you get the error that you received.

This is a simple fix. We just need to serialise the Buffer to a string when we encrypt text, and deserialise the encrypted string we receive when we decrypt text.

In this example, I use base64 encoding because it is fairly compact when representing binary data.

var config = {
  cryptkey: crypto.createHash('sha256').update('Nixnogen').digest(),
  iv: 'a2xhcgAAAAAAAAAA'
}

function encryptText (text) {
  console.log(config.cryptkey)
  var cipher = crypto.createCipheriv('aes-256-cbc', config.cryptkey, config.iv)
  return Buffer.concat([
    cipher.update(text),
    cipher.final()
  ]).toString('base64') // Output base64 string
}

function decryptText (text) {
  console.log(config.cryptkey)
  if (text === null || typeof text === 'undefined' || text === '') {
    return text
  }
  var decipher = crypto.createDecipheriv('aes-256-cbc', config.cryptkey, config.iv)
  return Buffer.concat([
    decipher.update(text, 'base64'), // Expect `text` to be a base64 string
    decipher.final()
  ]).toString()
}

var encrypted = encryptText('text') // 8xXuS7jLG6crqJFHHB5J5A==
var decrypted = decryptText(encrypted) // text
Adaline Simonian
  • 4,596
  • 2
  • 24
  • 35