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'] ) }