diff --git a/src/pbkdf.ts b/src/pbkdf.ts new file mode 100644 index 0000000..c5cfbc8 --- /dev/null +++ b/src/pbkdf.ts @@ -0,0 +1,29 @@ +import logger from 'log' + +const log = logger('crypto:pbkdf') + +export async function pbkdf(password: string, salt: Uint8Array, usages: KeyUsage[]): Promise { + log.trace('derive') + log.debug(`Usages : ${usages}`) + + 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..0c5c42d --- /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: KeyUsage[] = ['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) + } +})