Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nodejs crypto.pbkdf2 result is different from CryptoJS.PBKDF2

I'm working with PBKDF2 on frontend (CryptoJS) and backend (Node.js), both the derived key must be equal so, I use the same salt, same algo, same number of iteration, same password, but the derived key is different.

This is the Browser/cryptoJS code, in comment the sample salt and key. (hex)

<script type="text/javascript" src="pbkdf2.js"></script>
<script type="text/javascript" src="sha512.js"></script>
<script>
var salt = CryptoJS.lib.WordArray.random(128 / 8);
var key512Bits = CryptoJS.PBKDF2('anacleto', salt, { hasher:CryptoJS.algo.SHA512, keySize: 512 / 32, iterations: 1 });
console.log(salt.toString(CryptoJS.enc.Hex));
// 1427f23fd32f8f9902768e7ab7c7ffad
console.log(key512Bits.toString(CryptoJS.enc.Hex));
// de3259de39fcc55531b91b4ffb2a6c29005c674cc95b3ec5bdf18412b6087d05921f3a0e4148fc34c88a04e980481d397a4c2b143edc0cb1bb5d7434ca3b4c25
</script>

And this is the nodeJS code

var crypto = require('crypto');
var salt_hex = '1427f23fd32f8f9902768e7ab7c7ffad';
var key_hex = 'de3259de39fcc55531b91b4ffb2a6c29005c674cc95b3ec5bdf18412b6087d05921f3a0e4148fc34c88a04e980481d397a4c2b143edc0cb1bb5d7434ca3b4c25';
var salt = new Buffer(salt_hex, 'hex');
crypto.pbkdf2('anacleto', salt.toString('utf8'), 1, 512/8, 'sha512', function (err, key) {
  if (err)
    throw err;
  var x = key.toString('hex');
  var y = key_hex;
  console.assert(x === y, '\n' + x + '\n !== \n' + y);
});

And the console comes up with this assertion error:

AssertionError: 
efcca398dc0eb07aec6dcf2239dae83b79c2f82212b2cc0a21270fe251c73c7ab69f0133e75bf3ca6159242826ff3f26c64075f72cf86c67ba1199af29f6d576 
!== 
de3259de39fcc55531b91b4ffb2a6c29005c674cc95b3ec5bdf18412b6087d05921f3a0e4148fc34c88a04e980481d397a4c2b143edc0cb1bb5d7434ca3b4c25

As you can see the key from node.js starts with "efcca" and the CryptoJS one start with "de325".

Where is the error? Maybe it's a different library implementation?? Shouldn't be the same derived key?

like image 917
TheZero Avatar asked Sep 29 '15 13:09

TheZero


Video Answer


1 Answers

When you do

var salt = CryptoJS.lib.WordArray.random(128 / 8);

You get random bytes. When you encode the salt to a UTF-8 string in node.js it will result in a different encoding than what node.js's crypto.pbkdf2 expects.

Change

crypto.pbkdf2('anacleto', salt.toString('utf8'), 1, 512/8,

to

crypto.pbkdf2('anacleto', salt, 1, 512/8,

or

crypto.pbkdf2('anacleto', salt.toString('binary'), 1, 512/8,
like image 152
Artjom B. Avatar answered Nov 03 '22 01:11

Artjom B.