diff --git a/src/kdf.ts b/src/kdf.ts index 7ce757d..05dd3b9 100644 --- a/src/kdf.ts +++ b/src/kdf.ts @@ -44,6 +44,9 @@ export async function kdf(mod: IKdfModule, password: Uint8Array): Promise { + if (globalThis?.crypto?.subtle) { + return await doPbkdf2WebCrypto(params, password); + } return pbkdf2( password, hexToBytes(params.salt), @@ -53,6 +56,40 @@ async function doPbkdf2(params: IPbkdf2KdfModule["params"], password: Uint8Array ); } +async function doPbkdf2WebCrypto(params: IPbkdf2KdfModule["params"], password: Uint8Array): Promise { + const passwordKey = await crypto.subtle.importKey( + "raw", + password, + "PBKDF2", + false, + ["deriveKey"], + ); + const key = await crypto.subtle.deriveKey( + { + name: "PBKDF2", + salt: hexToBytes(params.salt), + iterations: params.c, + hash: pickHash(params.prf.slice(5)), + }, + passwordKey, + { name: "AES-GCM", length: params.dklen * 8 }, + true, + ["encrypt", "decrypt"] + ); + return new Uint8Array(await crypto.subtle.exportKey("raw", key)); +} + +function pickHash(hash: string): string { + hash = hash.toLowerCase(); + if (hash === "sha256") { + return "SHA-256"; + } else if (hash === "sha512") { + return "SHA-512"; + } else { + throw new Error("Invalid hash type"); + } +} + async function doScrypt(params: IScryptKdfModule["params"], password: Uint8Array): Promise { return scrypt( password,