dchest / scrypt-async-js

Fast "async" scrypt implementation in JavaScript
http://dchest.github.io/scrypt-async-js/
BSD 2-Clause "Simplified" License
139 stars 26 forks source link

The hash output does not match with those of node-scrypt #35

Closed snshn closed 7 years ago

snshn commented 7 years ago

First of all, I have to say that this scrypt implementation is a very impressive piece of software and I wanted to thank you for sharing it with everyone.

I've been using it for a project of mine on the client side, and I've noticed that the results that I get from it differ from those that I get from the scrypt npm (https://github.com/barrysteyn/node-scrypt) while providing the exact same settings.

My code base is in Meteor so there's no easy way to share it, but please take a look at these two snippets of code and let me know if it's me doing something wrong, or there's something wrong with the code of the library that I could perhaps pinpoint and issue a patch for?

Front-end:

Tinytest.addAsync("app:encryption scrypt.js vs scrypt NPM", function (test, onComplete) {
  var inputString = "string!";
  var salt = "boo";

  scrypt(inputString, salt, 8, 1, 16, 1, function (res) {

    Meteor.call('scrypt-npm-hash', inputString, { N: 8, r: 1, p: 1 }, 16, salt, function (error, result) {
      test.equal(result, res, 'Expected the values to be equal');
      onComplete();
    });
  }, 'hex');
});

Back-end (to run the NPM):

var scrypt = Npm.require("scrypt");

Meteor.methods({
  'scrypt-npm-hash': function (input, options, length, salt) {
    return scrypt.hashSync(input, options, length, salt).toString("hex");
  }
});

The hashes that I get on the front end and from the back end are 0c6d9c3df862dc8abbdae7623367066e and 4e58712e98444c547d1e3b710fc79afe respectively. I assume they have to be equal since the input parameters are the same for both.

Thanks.

dchest commented 7 years ago

Thank you for your kind words.

scrypt(inputString, salt, 8, 1, 16, 1, function (res) {

Legacy API accents log2(N), not N, so you have logN = 8 meaning N = 28 = 256. Either specify 3 here (23 = 8) or use the new API:

 scrypt(inputString, salt, { N: 8, r: 1, p: 1, dkLen: 16 }, function (res) {

Speaking of values, N=8 is too small, the minimum recommended value is 16384 for 16 MiB of RAM per hash. r=1 isn't an optimal block size for current machines, always use r=8.