10

I'm having weird issues with Node's crypto library. I wrote this simple AES testing script:

var cipher = crypto.createCipher('aes-256-cbc','InmbuvP6Z8')
var text = "123|123123123123123";
cipher.update(text,'utf8','hex')
var crypted = cipher.final('hex')
var decipher = crypto.createDecipher('aes-256-cbc','InmbuvP6Z8')
decipher.update(crypted,'hex','utf8')
var dec = decipher.final('utf8')

When I do console.log(dec), it's null. For some reason if I set test to "123|123123", it works. So why does "123|123123" work but "123|123123123123123" doesn't?

gevorg
  • 4,835
  • 4
  • 35
  • 52
Mike
  • 113
  • 1
  • 2
  • 6

3 Answers3

29

You need to store the return from cipher.update as well as cipher.final to be sure you have everything.

cipher.update "returns the enciphered contents, and can be called many times with new data as it is streamed":

http://nodejs.org/docs/v0.2.5/api.html#cipher-update-247

cipher.final "returns any remaining enciphered contents".

I think you just append the results with each call like this:

var crypto = require('crypto');
var cipher = crypto.createCipher('aes-256-cbc','InmbuvP6Z8');
var text = "123|123123123123123";
var crypted = cipher.update(text,'utf8','hex');
crypted += cipher.final('hex');
var decipher = crypto.createDecipher('aes-256-cbc','InmbuvP6Z8');
var dec = decipher.update(crypted,'hex','utf8');
dec += decipher.final('utf8');

I get '12443a347e8e5b46caba9f7afc93d71287fbf11169e8556c6bb9c51760d5c585' for crypted and '123|123123123123123' for dec in the above with node v0.2.5

Mrchief
  • 75,126
  • 20
  • 142
  • 189
RandomEtc
  • 1,976
  • 1
  • 18
  • 17
  • 3
    RandomEtc is correct, remember that in node.js, everything is streamlined for, well, streams. The hash and cipher functions can be updated with text any number of times, which just adds text to it, but to get the result, you have to do a hash.digest or cipher.final – Vanwaril Jan 02 '11 at 18:55
  • RandomEtc, thanks for your answer to this. It got me there on crypto stuff finally! :) – James P. Wright Jul 13 '11 at 03:56
  • @RandomEtc. Can you help me to convert this code to javascript? – Suresh Pattu Mar 03 '20 at 08:39
  • Cipher cipher = Cipher.getInstance(ALGORITHM); byte[] messageArr = message.getBytes(); SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(key), "AES"); byte[] ivParams = new byte[16]; byte[] encoded = new byte[messageArr.length + 16]; System.arraycopy(ivParams, 0, encoded, 0, 16); System.arraycopy(messageArr, 0, encoded, 16, messageArr.length); cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(ivParams)); – Suresh Pattu Mar 03 '20 at 08:42
  • byte[] encryptedBytes = cipher.doFinal(encoded); encryptedBytes = Base64.getEncoder().encode(encryptedBytes); return new String(encryptedBytes); – Suresh Pattu Mar 03 '20 at 08:42
8

RandomEtc is correct, but just in case anyone stumbling on this question is using 'base64' as their encoding: Don't. Stick to 'hex'. At least as of 0.4.2, there's a bug that can result in corrupted data when 'base64' is used. See: https://github.com/joyent/node/issues/738/

Trevor Burnham
  • 76,828
  • 33
  • 160
  • 196
1

Please note that the += operator will not work in later versions of node.js. Please follow the advice given in Node.js Crypto class returning different results with updated version and use Buffer.concat()

Community
  • 1
  • 1
wdhilliard
  • 135
  • 11