node-scrypt icon indicating copy to clipboard operation
node-scrypt copied to clipboard

Lets create a new major version of Scrypt

Open barrysteyn opened this issue 7 years ago • 12 comments

Hi everyone

I would like to create a new major version of Scrypt, Scrypt version 7. So this could (and actually will) be breaking changes.

Can I get some discussion/feedback about what should be in here.

barrysteyn avatar Mar 02 '17 21:03 barrysteyn

The hash/hashSync functions patch is at the top of my wishlist.

BrandonZacharie avatar Mar 02 '17 21:03 BrandonZacharie

Excellent @BrandonZacharie

Everyone, please keep the suggestions coming.

barrysteyn avatar Mar 02 '17 22:03 barrysteyn

Having a quick look at scrypt-async-js, I like @dchest’s idea of accepting either N or logN. You could do something like if (params.N > 256) params.N = Math.log(params.N)*Math.LOG2E;. I don’t think there would be any ambiguity, as I can’t imagine anyone would actually want to use logN <= 8!

chrisveness avatar Mar 02 '17 23:03 chrisveness

@chrisveness I wouldn't do this, I think just accepting N is good enough and standardized between implementations, and my logN thing was a mistake, which I fixed in "modern API" (still allowing to specify logN only for backwards compatibility) . Also, N can theoretically be any number, not a power of two, it's just all implementations of scrypt accept only a power of two for simplicity. Those who want to use logN can just pass 1<<logN (up to logN=30) or Math.pow(2, logN). Your proposal is also error-prone: while not recommended, N <= 8 is a perfectly valid input, and it would be very strange if function interpreted different range of numbers differently.

dchest avatar Mar 02 '17 23:03 dchest

Colin Percival says “The parameter N must be a power of 2 greater than 1” (www.tarsnap.com/scrypt.html), so allowing any value of N would not seem a good idea for standardisation.

I like to be able to work with logN as I can immediately recognise the difference in workload between 14 and 20, whereas I have to get my calculator out to recognise workloads of 16384 or 1048576 – though I agree, I could fairly easily use 2**14...

Edit: though accepting either N or logN for scrypt.kdf() paramsObject would make it a non-breaking change...

chrisveness avatar Mar 02 '17 23:03 chrisveness

Colin Percival says “The parameter N must be a power of 2 greater than 1” (www.tarsnap.com/scrypt.html), so allowing any value of N would not seem a good idea for standardisation.

True, that's because none of the implementations support not-power-of-two N for simplicity, but the function itself is defined in the paper without such restrictions. Here's a footnote from page 6:

"We expect that for reasons of performance and simplicity, implementors will restrict N to being a power of 2, in which case the function Integerify can be replaced by reading the first (or last) machine-length word from a k-bit block."

I like to be able to work with logN as I can immediately recognise the difference in workload between 14 and 20, whereas I have to get my calculator out to recognise workloads of 16384 or 1048576 – though I agree, I could fairly easily use 2**14...

I'm also used to logN, but even nicer would be to write 16 << 10 for 16384, 1024 << 10 for 1048576, etc. This way with r=8 you can assume the first number is the number of mebibytes of memory to use. Very convenient :)

dchest avatar Mar 03 '17 00:03 dchest

Is that implementors including himself? :)

chrisveness avatar Mar 03 '17 00:03 chrisveness

Yes, the reference implementation allows only powers of two.

dchest avatar Mar 03 '17 00:03 dchest

Ensuring that N is a power of 2 should not force us to use a logarithm. If we want to stick to the way Colin has done things in his source code, we could make a check for a power 2 and fail. Or if that approach would be too jarring, we could round up (or down!! - probably up) to the nearest power of two and print a warning to the console. What do you guys think?

barrysteyn avatar Mar 03 '17 17:03 barrysteyn

I think throwing an error is the right thing to do. That's how most of implementations behave.

In my opinion, rounding up or down isn't the correct way to do this, since in theory any number can be used, we just don't support it. Let's not introduce surprises.

dchest avatar Mar 03 '17 17:03 dchest

@dchest - okay, I have no problem with throwing an error.

barrysteyn avatar Mar 07 '17 01:03 barrysteyn

For consistency with other libraries, I think it would be better to use N for exposed interfaces (including params) instead of logN, and do a power of 2 check in the wrappers. Creating confusion over N and logN seems like a bad thing for a security-sensitive library.

Either way, it would be good to make the internal naming consistent. Currently you have1:

   obj->Set(Nan::New("N").ToLocalChecked(), Nan::New<Integer>(logN));

the less obvious2, 3:

  const unsigned int result = Hash(key_ptr, key_size, salt_ptr, salt_size, params.N, params.r, params.p, hash_ptr, hash_size);
  ...
  Hash(const uint8_t* key, size_t keylen, const uint8_t *salt, size_t saltlen, uint64_t logN, uint32_t r, uint32_t p, uint8_t *buf, size_t buflen) {

and the README examples haven't been updated.

Happy to help out if you need a hand with this.

marksteward avatar Nov 27 '18 12:11 marksteward