3

I am beginnging to wonder if the implementation of AES is different across libraries..

Currently i have a plaintext encrypted with PyCrypto.
Im trying to decrypt the ciphertext with Node.js's Crypto Library..

Basically with PyCrypto..
im using AES-128-CBC with a random generated IV. (which decrypts perfectly in PyCrypto)

However..
On Node.js im doing this

var buf = new Buffer(ciphertext)
var decipher = crypto.createDecipher('aes-128-cbc',aeskey)
buf = decipher.update(buf,'binary', 'binary')
buf += decipher.final('binary')

Which spits out a bunch of Garbage.... ( changing 'binary' to hex/utf8 doesnt help)

As i am using CBC (Cipher Block Chaining)...
i am prepending the IV to the beginning of the ciphertext (16 blocks).. In PyCrypto this works perfectly, similarly to the specification of PGP, CFB usage..

Does anyone know for what reason this is not working???

Am i expecting too much of Node.js's standard libraries?

Arenstar
  • 139
  • 7

5 Answers5

1

Documentation does not mention this, but aeskey you're passing to crypto.createDecipher is not the key, but a password, handled to OpenSSL's EVP_BytesToKey function.

To pass the actual raw key data one should use (presently undocumented) crypto.createDecipheriv(cipher, key, iv) function. This applies to ECB mode too, even though there's no IV in ECB.

If this fails, I think, the first step in debugging would be to try with AES KATs to see whenever the decryption code is correct.

I've tripped on a similar issue here: https://github.com/joyent/node/issues/1318

drdaeman
  • 11,159
  • 7
  • 59
  • 104
0

AES is a rijndael standard. It shouldn't be different. You should look into data types and default settings that are hidden. Something must be set different between the two. The key sizes might be different as 128 bit "hello" is padded with zeros I think and a smaller key would start with "hello" but have a smaller padding, therefore different.

Will03uk
  • 3,346
  • 8
  • 34
  • 40
  • Well... There is a bug it seems.... http://groups.google.com/group/nodejs-dev/browse_thread/thread/d279b6109abc5f21/e506524e432d7463?lnk=gst&q=crypto#e506524e432d7463 – Arenstar Mar 18 '11 at 01:52
0

The short answer to your question is: Yes, AES is the same in PyCrypto and Node.js' crypto module. Node's crypto is just a wrapper around openssl on your system, and PyCrypto is interoperable with OpenSSL (see http://lists.dlitz.net/pipermail/pycrypto/2010q4/000301.html).

Having said that, there are definitely bugs in the Node crypto module (though I've only experienced problems with base64 encoding, myself). So whether it's a bug or not, the problems you're experiencing are almost certainly happening in the data encoding/decoding stages.

What does your ciphertext look like? Is it a hexadecimal string? If so, then you need to do

buf = decipher.update(buf, 'hex', 'binary')
Trevor Burnham
  • 76,828
  • 33
  • 160
  • 196
  • For Clarity.. please read this.. http://groups.google.com/group/nodejs/browse_thread/thread/6a35a33f2e5003e3 Cheers – Arenstar Mar 18 '11 at 18:20
  • I just created a new library for encryption/decryption under Node, because crypto issues have been bugging me as well: https://github.com/TrevorBurnham/cipherpipe It's just a thin wrapper around `openssl`. Give it a try and let me know what you think. – Trevor Burnham Mar 18 '11 at 18:30
  • npm ERR! 404 Looks like 'cipherpip' is not in the npm registry. npm ERR! 404 You should bug the author to publish it. :( ... I would love to try this – Arenstar Mar 18 '11 at 18:48
  • Whoops, forgot to `npm publish`. Sorry about that. Try it again. – Trevor Burnham Mar 18 '11 at 21:03
  • /usr/local/lib/node/.npm/cipherpipe/0.1.0/package/lib/cipherpipe.js:6 return '"' + str.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"'; ^ TypeError: Cannot call method 'replace' of undefined ... i cant use your frombase64 method ... Using the base64 as in my example, and trying to decode Aes.. results in.. "undefined" being returned :( – Arenstar Mar 18 '11 at 21:30
  • Could you raise an issue on Github so we can figure it out over there? Thanks. – Trevor Burnham Mar 19 '11 at 00:33
  • I think the issues have been fixed now. Give it another whirl (with version 0.1.1) and raise an issue on Github if it's still giving you grief. – Trevor Burnham Mar 19 '11 at 14:07
0

That's not how IV works in Node, you have to use crypto.createDecipheriv(cipher, key, iv) instead, otherwise you get a default baked-in one. Even in PyCrypto you should be using the third argument to AES.new as the IV, not stuffing it into the bytestream.

SilverbackNet
  • 2,076
  • 17
  • 29
  • In Node 0.4.2, there is no mention of usings IV's ??? If you take a look at the CBC design, you will understand, prepending it and using zeros as the IV will kick off the chain correctly..leaving a garbage block at the beginning.. This is similar to how pgp functions.. – Arenstar Mar 19 '11 at 17:50
  • Hmm i did find, crypto.createDecipheriv(cipher, key, iv) in the code.. However it is still not working :( – Arenstar Mar 19 '11 at 18:10
0

Make sure you use the same key and IV in both pycrypto and node.js!! Not only that, but make sure you have the same encoding in both ends:

cipher = AES.new(key.decode('hex'), AES.MODE_CBC, iv.decode('hex'))
text = json.dumps(payload)  
pad = lambda s: s + (16 - len(s) % 16) * '\x07'     
encryptedText = base64.b64encode(cipher.encrypt(pad(text)))

Then in node.js (sorry, no easy access to that code now), also make sure you decode your key and iv to hex

Ricardo Villamil
  • 5,031
  • 2
  • 30
  • 26