diff --git a/packages/connect/src/api/firmware/verifyEntropy.ts b/packages/connect/src/api/firmware/verifyEntropy.ts index b6344f539e8..355a77fea0e 100644 --- a/packages/connect/src/api/firmware/verifyEntropy.ts +++ b/packages/connect/src/api/firmware/verifyEntropy.ts @@ -1,6 +1,6 @@ import { entropyToMnemonic, mnemonicToSeed } from 'bip39'; import { hmac } from '@noble/hashes/hmac'; -import { pbkdf2 } from '@noble/hashes/pbkdf2'; +import { crypto } from '@noble/hashes/crypto'; import { sha256 } from '@noble/hashes/sha256'; import { randomBytes } from '@noble/hashes/utils'; @@ -21,16 +21,34 @@ const BASE_ITERATION_COUNT = 10000; const ROUND_COUNT = 4; // https://github.com/trezor/python-shamir-mnemonic/blob/master/shamir_mnemonic/cipher.py -const roundFunction = (i: number, passphrase: Buffer, e: number, salt: Buffer, r: Buffer) => { +const roundFunction = async (i: number, passphrase: Buffer, e: number, salt: Buffer, r: Buffer) => { const data = Buffer.concat([Buffer.from([i]), passphrase]); const iterations = Math.floor((BASE_ITERATION_COUNT << e) / ROUND_COUNT); - const result = pbkdf2(sha256, data, Buffer.concat([salt, r]), { - c: iterations, - dkLen: r.length, - }); - - return Buffer.from(result); + // '@noble/hashes/pbkdf2' takes ~ 8sec. in the web build + // const result = pbkdf2(sha256, data, Buffer.concat([salt, r]), { + // c: iterations, + // dkLen: r.length, + // }); + + // Nodejs only + // return crypto.pbkdf2Sync(data, Buffer.concat([salt, r]), iterations, r.length, 'sha256'); + + // Nodejs + WebCrypto equivalent + const { subtle } = crypto as Crypto; + const key = await subtle.importKey('raw', data, 'PBKDF2', false, ['deriveBits']); + const bits = await subtle.deriveBits( + { + name: 'PBKDF2', + hash: 'SHA-256', + salt: Buffer.concat([salt, r]), + iterations, + }, + key, + r.length * 8, + ); + + return Buffer.from(bits); }; // https://github.com/trezor/python-shamir-mnemonic/blob/master/shamir_mnemonic/cipher.py @@ -48,7 +66,7 @@ const xor = (a: Buffer, b: Buffer) => { // https://github.com/trezor/python-shamir-mnemonic/blob/master/shamir_mnemonic/cipher.py // simplified "decrypt" function -const entropyToSeedSlip39 = (encryptedSecret: Buffer) => { +const entropyToSeedSlip39 = async (encryptedSecret: Buffer) => { const iterationExponent = 1; // const identifier = 0; // const extendable = true, @@ -59,7 +77,7 @@ const entropyToSeedSlip39 = (encryptedSecret: Buffer) => { let l = encryptedSecret.subarray(0, half); let r = encryptedSecret.subarray(half); for (let round = ROUND_COUNT - 1; round >= 0; round--) { - const f = roundFunction(round, passphrase, iterationExponent, salt, r); + const f = await roundFunction(round, passphrase, iterationExponent, salt, r); const rr = xor(l, f); l = r; r = rr;