4

I've got the following Java code that I'd like to port to Node.js:

// Java

byte[] rawKey = "deadbeefdeadbeef".getBytes("us-ascii");
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cip = Cipher.getInstance("AES/ECB/NoPadding");
cip.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] plaintext = cip.doFinal(ciphertext, 0, ciphertext.length);

Here's my attempt with Node.js, using streams

// JS, using the crypto streams API

var decipher = crypto.createDecipher('aes-128-ecb', 'deadbeefdeadbeef');
decipher.setAutoPadding(false);
decipher.pipe(concat(function(plaintext) { console.log(plaintext); });
decipher.end(ciphertext);

And, also a Node.js attempt using the older .update() and .final() API:

// JS, using the `.update()` and `.final()` API

var decipher = crypto.createDecipher('aes-128-ecb', 'deadbeefdeadbeef');
decipher.setAutoPadding(false);
var pieces = [];
pieces.push(new Buffer(decipher.update(ciphertext)));
pieces.push(new Buffer(decipher.final()));
var plaintext = Buffer.concat(pieces);

Both of these versions produce the same output of the correct length (the same length as the input), but this output is not the same plaintext that is produced by the Java version of the decipher operating on the same input buffer. How can I set up a Node.js decipher like the Java decipher configured above?

Thank you.

6
  • You seem to be using AES-128 in the Java code while you specify AES-256 in the JS code. I'm not sure how the JS API can accept a 128-bit key for a 256-bit cipher; perhaps it's performing some sort of key derivation? Commented Feb 9, 2014 at 11:24
  • My bad, that was a copy/paste from old code! Thank you for pointing it out. I had figured out as much around the time of posting this question. I've since had this problem solved, and will post an answer soon. Though, I'm not versed in crypto and don't understand the meaning of the answer: using crypto.createDecipheriv('aes-128-ecb', 'deadbeefdeadbeef', ''); did the trick. Commented Feb 9, 2014 at 16:51
  • @ntoskrnl: And yes, for a while I was using aes-256-ecb with a 128-bit key and it wasn't throwing or indicating error otherwise. Just producing undesired decrypt output. Commented Feb 9, 2014 at 16:54
  • @dimadima As your ciphertext is not protected for integrity nor authenticity, your ciphertext will happily decrypt to random bytes. Normally this is caught by the unpadding (which can have disastrous results itself because of padding oracle attacks) but otherwise the output is simply random. You can even decrypt with DES and get a result. Add a MAC or HMAC to protect against such things (and do use CBC and padding, your current solution is probably insecure on many levels). Commented Feb 11, 2014 at 12:48
  • What is the concat function in decipher.pipe(concat(...? Commented Aug 19, 2015 at 2:15

1 Answer 1

4

createDecipher actually does not use a key as you do in Java. It uses a password, which is fed into a Password Based Key Derivation Function (PBKDF) to derive the key. Hence with a different key and no method of checking the correctness of the key, you will get random plain text.

The Node.js API is not very well named, the functions createDecipher and createDecipheriv suggest that the latter is just the same as the former, with the addition of an IV. Instead, createDecipher adds an entire key derivation function to the mix.

Sign up to request clarification or add additional context in comments.

4 Comments

@dimadima Answered it for you, if you don't mind, as I do know why this made such a big difference. Please indicate if you made additional changes to your code to make this work.
Thank you very much. Yes, changing to the IV function was all that was necessary. To be specific: crypto.createDecipher('aes-128-ecb', 'deadbeefdeadbeef') -> crypto.createDecipheriv('aes-128-ecb', 'deadbeefdeadbeef', '')
With v0.10.35 node always throws the error "node-crypto : Invalid IV length " if I use the proposed solution - any workaround?
@Skomski Try crypto.randomBytes(size) to create the IV, make sure you understand the way NodeJS handles buffers and streaming. The IV can be prefixed to the ciphertext.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.