Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace create hash with sha.js #173

Conversation

webmaster128
Copy link

Based on #172 (merge #172 first).

Closes #170

Turns out this is not enought to get create-hash out of the dependency tree because pbkdf2 uses it.
However, it is possible to implement pbkdf2 manually or get that fixed in the next step.

@junderw
Copy link
Member

junderw commented Dec 6, 2021

Made a quick dirty impl of pbkdf2 using sha.js with SHA512, 64 dlen, and 2048 iterations hard coded.
It was 5x~6x slower :-|

... we should probably section this off to a browser section...
People in Node should not have to suffer even a 2x slowdown because of the browser.

import * as sha from 'sha.js';

const sha512 = (data: Buffer | string): Buffer => {
  return sha('sha512')
    .update(data)
    .digest();
};

const xorBuf = (a: Buffer, b: Buffer): Buffer => {
  const ret = Buffer.allocUnsafe(a.length);
  for (let i = 0; i < a.length; i++) {
    ret[i] = a[i] ^ b[i];
  }
  return ret;
};

const hmac = (data: Buffer | string, key: Buffer | string): Buffer => {
  const k = key.length > 128 ? sha512(key) : Buffer.from(key as any, 'utf8');
  const buf = Buffer.alloc(128);
  k.copy(buf);
  const oKey = Buffer.from(buf);
  const iKey = Buffer.from(buf);
  for (let i = 0; i < 128; i++) {
    oKey[i] = oKey[i] ^ 0x5c;
    iKey[i] = iKey[i] ^ 0x36;
  }
  return sha512(
    Buffer.concat([
      oKey,
      sha512(Buffer.concat([iKey, Buffer.from(data as any, 'utf8')])),
    ]),
  );
};

const ITERS = 2048;

export function pbkdf2(
  password: Buffer | string,
  salt: Buffer | string,
): Buffer {
  const UArray = [];
  UArray.push(
    hmac(
      Buffer.concat([
        Buffer.from(salt as any, 'utf8'),
        Buffer.from([0, 0, 0, 1]),
      ]),
      password,
    ),
  );
  let ret = UArray[0];
  for (let i = 1; i < ITERS; i++) {
    const hash = hmac(UArray[i - 1], password);
    UArray.push(hash);
    ret = xorBuf(ret, hash);
  }
  return ret;
}

@webmaster128
Copy link
Author

... we should probably section this off to a browser section...
People in Node should not have to suffer even a 2x slowdown because of the browser.

I doubt "browsers" is the right category. JS environments with/without Crypto APIs is probably the better classification. SubtleCrypto is available in Node.js 15.

It should not be too hard to come up with a pbkdf2 implementation that uses

  1. SubtleCrypto
  2. Node.js crypto module
  3. Pure-JS fallback

as long as only SHA2 is needed.

@junderw
Copy link
Member

junderw commented Dec 6, 2021

I am not comfortable raising the requirement of NodeJS above v14 right now, so SubtleCrypto for Node is not possible.

@junderw
Copy link
Member

junderw commented Dec 6, 2021

Maybe after v12 EOL 2022-04-30

@webmaster128
Copy link
Author

Sure, me neither. But you can have an implementation that uses 1., 2. or 3. depending on availability.

@webmaster128
Copy link
Author

webmaster128 commented Dec 6, 2021

So my current thinking given your input is reimplementing pbkdf2

  • in TypeScript
  • supporting SHA2 only
  • targeting reasonabily modern JS environments(native async/await and Uint8Array support)
  • removal of the sync variant
  • using SubtleCrypto, Node.js crypto module and pure-JS fallback depending on availability
  • using the same SHA2 implementation for pbkdf2 and deriveChecksumBits

@infodusha
Copy link

Any chance this change will be merged?

@webmaster128
Copy link
Author

I'm not planning to continue working on this. But feel free to use my commits if you want to finalize it.

@paulmillr
Copy link
Contributor

not relevant anymore

"@noble/hashes": "^1.2.0"

@junderw junderw closed this Mar 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use more lightweight sha256 implementation
4 participants