diff --git a/packages/crypto/src/bip39.ts b/packages/crypto/src/bip39.ts index 4b5f6d12..1d90ca16 100644 --- a/packages/crypto/src/bip39.ts +++ b/packages/crypto/src/bip39.ts @@ -1,5 +1,4 @@ import { toUtf8 } from "@cosmjs/encoding"; -import { pbkdf2 } from "pbkdf2"; import { sha256 } from "./sha"; @@ -2206,25 +2205,51 @@ export class Bip39 { const mnemonicBytes = toUtf8(normalize(mnemonic.toString())); const salt = "mnemonic" + (password ? normalize(password) : ""); const saltBytes = toUtf8(salt); - return this.pbkdf2(mnemonicBytes, saltBytes, 2048, 64, "sha512"); + return this.pbkdf2Sha512(mnemonicBytes, saltBytes, 2048, 64); } // convert pbkdf2's callback interface to Promise interface - private static async pbkdf2( + private static async pbkdf2Sha512( secret: Uint8Array, salt: Uint8Array, iterations: number, keylen: number, - digest: string, ): Promise { - return new Promise((resolve, reject) => { - pbkdf2(secret, salt, iterations, keylen, digest, (err, derivedKey) => { - if (err) { - reject(err); - } else { - resolve(new Uint8Array(derivedKey)); - } + const g: any = globalThis; + let subtle = g.crypto && g.crypto.subtle; + if (!subtle) { + const crypto = await import("crypto"); + subtle = (crypto as any).webcrypto.subtle; + } + + if (subtle) { + return subtle + .importKey("raw", secret, { name: "PBKDF2" }, false, ["deriveBits"]) + .then((key: Uint8Array) => + subtle + .deriveBits( + { + name: "PBKDF2", + salt: salt, + iterations: iterations, + hash: { name: "SHA-512" }, + }, + key, + keylen * 8, + ) + .then((buffer: ArrayBuffer) => new Uint8Array(buffer)), + ); + } else { + const module = await import("crypto"); + return new Promise((resolve, reject) => { + module.pbkdf2(secret, salt, iterations, keylen, "sha512", (error, result) => { + if (error) { + reject(error); + } else { + resolve(Uint8Array.from(result)); + } + }); }); - }); + } } }