import logger from 'log' const log = logger('crypto:kdf') export enum Usage { sign, wrap, } export async function hkdf(key: Uint8Array, usage: Usage) : Promise { log.trace("HKDF") log.trace(`usage : ${usage === Usage.sign ? 'sign' : 'wrap'}`) const material = await crypto.subtle.importKey( "raw", key, "HKDF", false, ["deriveKey", "deriveBits"], ) if (usage === Usage.wrap) { return crypto.subtle.deriveKey( { name: "HKDF", hash: "SHA-512", salt: new Uint8Array(32), info: new TextEncoder().encode("wrap"), }, material, {name: "AES-GCM", length: 256}, false, ["wrapKey", "unwrapKey"], ) } else if (usage === Usage.sign) { const buffer = await crypto.subtle.deriveBits( { name: "HKDF", hash: "SHA-512", salt: new Uint8Array(32), info: new TextEncoder().encode("sign"), }, material, 512 ) return new Uint8Array(buffer) } else { log.warn(`Called HKDF with unknown enum value : ${usage}`) throw "I don't even know what to say." } } export async function pbkdf(salt: Uint8Array, password: string) : Promise { log.trace("PBKDF") const material = await crypto.subtle.importKey( "raw", new TextEncoder().encode(password), "PBKDF2", false, ["deriveBits"], ) const buffer = await crypto.subtle.deriveBits( { name: "PBKDF2", salt, iterations: 250_000, hash: "SHA-512", }, material, 256, ) return new Uint8Array(buffer) } export function ecdh(privkey: CryptoKey, pubkey: CryptoKey) : Promise { log.trace("ECDH") return crypto.subtle.deriveKey( { name: "ECDH", public: pubkey, }, privkey, { name: "AES-GCM", length: 256, }, false, ["wrapKey", "unwrapKey"], ) }