UNPKG

@nfen/webcrypto-ts

Version:
173 lines (162 loc) 4.38 kB
/** * Code related to HMAC * @module */ import { getKeyUsagePairsByAlg } from "../key_usages.js"; import * as params from "../params.js"; import * as proxy from "../proxy.js"; import { Alg as SHA } from "../sha/shared.js"; import * as WebCrypto from "../webcrypto.js"; export interface HmacCryptoKey extends CryptoKey { _hmacKeyBrand: any; } export interface HmacProxiedCryptoKey extends proxy.ProxiedCryptoKey<HmacCryptoKey> { sign: (data: BufferSource) => Promise<ArrayBuffer>; verify: (signature: BufferSource, data: BufferSource) => Promise<boolean>; exportKey: (format: KeyFormat) => Promise<JsonWebKey | ArrayBuffer>; } /** @hidden */ export const handler: ProxyHandler<HmacCryptoKey> = { get(target: HmacCryptoKey, prop: string) { switch (prop) { case "self": return target; case "sign": return (data: BufferSource) => sign(target, data); case "verify": return (signature: BufferSource, data: BufferSource) => verify(target, signature, data); case "exportKey": return (format: KeyFormat) => exportKey(format, target); } return Reflect.get(target, prop); }, }; export namespace Alg { export enum Code { HMAC = "HMAC", } export type Codes = `${Code}`; } /** * Generate a new HMAC key * @example * ```ts * const key = await HMAC.generateKey(); * ``` */ export const generateKey = async ( algorithm: Omit<params.EnforcedHmacKeyGenParams, "name"> = { hash: SHA.Variant.SHA_512, }, extractable: boolean = true, keyUsages?: KeyUsage[] ): Promise<HmacProxiedCryptoKey> => { const key = await WebCrypto.generateKey< HmacCryptoKey, params.EnforcedHmacKeyGenParams >( { ...algorithm, name: Alg.Code.HMAC, }, extractable, keyUsages ?? getKeyUsagePairsByAlg(Alg.Code.HMAC) ); return proxy.proxifyKey<HmacCryptoKey, HmacProxiedCryptoKey>(handler)(key); }; /** * Import an HMAC key from the specified format * @example * ```ts * const key = await HMAC.importKey("jwk", jwk, {hash: "SHA-512"}); * ``` */ export const importKey = async ( format: KeyFormat, key: BufferSource | JsonWebKey, algorithm: Omit<params.EnforcedHmacImportParams, "name">, extractable: boolean = true, keyUsages?: KeyUsage[] ): Promise<HmacProxiedCryptoKey> => { const importedKey = await WebCrypto.importKey< HmacCryptoKey, params.EnforcedHmacImportParams >( format as any, key as any, { ...algorithm, name: Alg.Code.HMAC }, extractable, keyUsages ?? getKeyUsagePairsByAlg(Alg.Code.HMAC) ); return proxy.proxifyKey<HmacCryptoKey, HmacProxiedCryptoKey>(handler)( importedKey ); }; /** * Export an HMAC key into the specified format * @example * ```ts * const jwk = await HMAC.exportKey("jwk", key.self); * ``` * @example * ```ts * const jwk = await key.exportKey("jwk"); * ``` */ export async function exportKey( format: KeyFormat, key: HmacCryptoKey ): Promise<JsonWebKey | ArrayBuffer> { return await WebCrypto.exportKey<HmacCryptoKey>(format as any, key); } /** * Sign a given payload * @example * ```ts * const message = new TextEncoder().encode("a message"); * const signature = await HMAC.sign(key.self, message); * ``` * ```ts * const message = new TextEncoder().encode("a message"); * const signature = await key.sign(message); * ``` */ export async function sign( key: HmacCryptoKey, data: BufferSource ): Promise<ArrayBuffer> { return await WebCrypto.sign<HmacCryptoKey, params.HmacKeyAlgorithm>( { name: Alg.Code.HMAC, }, key, data ); } /** * Verify a given signature * @example * ```ts * const isVerified = await HMAC.verify(key, signature, message); * ``` * @example * ```ts * const isVerified = await key.verify(signature, message); * ``` */ export async function verify( key: HmacCryptoKey, signature: BufferSource, data: BufferSource ): Promise<boolean> { return await WebCrypto.verify<HmacCryptoKey, params.HmacKeyAlgorithm>( { name: Alg.Code.HMAC, }, key, signature, data ); }