For some odd reason, Node's built-in Cipher and Decipher classes aren't working as expected. The documentation states that cipher.update
"Returns the enciphered contents, and can be called many times with new data as it is streamed."
The docs also state that cipher.final
"Returns any remaining enciphered contents."
However, in my tests you must call cipher.final to get all of the data, thus rendering the Cipher object worthless, and to process the next block you have to create a new Cipher object.
var secret = crypto.randomBytes(16) , source = crypto.randomBytes(8) , cipher = crypto.createCipher("aes128", secret) , decipher = crypto.createDecipher("aes128", secret); var step = cipher.update(source); var end = decipher.update(step); assert.strictEqual(source.toString('binary'), end); // should not fail, but does Note that this happens when using crypto.createCipher or crypto.createCipheriv, with the secret as the initialization vector. The fix is to replace lines 6 and 7 with the following:
var step = cipher.update(source) + cipher.final(); var end = decipher.update(step) + decipher.final(); But this, as previously noted, renders both cipher and decipher worthless.
This is how I expect Node's built-in cryptography to work, but it clearly doesn't. Is this a problem with how I'm using it or a bug in Node? Or am I expecting the wrong thing? I could go and implement AES directly, but that would be time-consuming and annoying. Should I just create a new Cipher or Decipher object every time I need to encrypt or decrypt? That seems expensive if I'm doing so as part of a stream.