bip39
bip39 copied to clipboard
Replace create hash with sha.js
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.
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;
}
... 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
- SubtleCrypto
- Node.js crypto module
- Pure-JS fallback
as long as only SHA2 is needed.
I am not comfortable raising the requirement of NodeJS above v14 right now, so SubtleCrypto for Node is not possible.
Maybe after v12 EOL 2022-04-30
Sure, me neither. But you can have an implementation that uses 1., 2. or 3. depending on availability.
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
Any chance this change will be merged?
I'm not planning to continue working on this. But feel free to use my commits if you want to finalize it.
not relevant anymore https://github.com/bitcoinjs/bip39/blob/a7ecbfe2e60d0214ce17163d610cad9f7b23140c/package.json#L38