diff --git a/index.ts b/index.ts index 617689f..35fb776 100644 --- a/index.ts +++ b/index.ts @@ -1,3 +1,4 @@ export * as signature from 'signature' export * as boxes from 'boxes' export * as JWT from 'jwt' +export {pbkdf} from './src/pbkdf' diff --git a/src/pbkdf.ts b/src/pbkdf.ts new file mode 100644 index 0000000..2fdfc53 --- /dev/null +++ b/src/pbkdf.ts @@ -0,0 +1,22 @@ +export async function pbkdf(password: string, salt: Uint8Array, usages: KeyUsage[]): Promise { + const keyMaterial = await window.crypto.subtle.importKey( + "raw", + new TextEncoder().encode(password), + "PBKDF2", + false, + ["deriveBits", "deriveKey"], + ) + + return crypto.subtle.deriveKey( + { + name: "PBKDF2", + iterations: 250_000, + hash: "SHA-512", + salt, + }, + keyMaterial, + {name: "AES-GCM", length: 256}, + false, + usages, + ) +} diff --git a/test/pbkdf.test.ts b/test/pbkdf.test.ts new file mode 100644 index 0000000..9a076e1 --- /dev/null +++ b/test/pbkdf.test.ts @@ -0,0 +1,18 @@ +import {expect, test} from 'bun:test' + +import {pbkdf} from 'pbkdf' + +test('Fields are set correctly', async () => { + const pwd = 'password' + const salt = new TextEncoder().encode('salt') + const usages = ['unwrapKey', 'encrypt'] + + const k1 = await pbkdf(pwd, salt, usages) + expect(k1.extractable).toBeFalse() + expect(k1.type).toBe('secret') + + expect(k1.usages.length).toBe(usages.length) + for (const usage of usages) { + expect(k1.usages).toContain(usage) + } +})