Source: algs/hmac.js

import { Buffer } from 'buffer'
import crypto from 'isomorphic-webcrypto'

/**
 * Algorithm parameters
 */
const params = {
  HS256: { hash: 'SHA-256' },
  HS512: { hash: 'SHA-512' },
}

/**
 * HMAC module.
 */
 export const HMAC = {
  /**
   * Signs the message with the key using the specified algorithm.
   * 
   * @param {String} alg
   * @param {Buffer|String} msg
   * @param {Key} key
   * @returns {Buffer}
   */
  async sign(alg, msg, key) {
    assertKey(key, alg)

    const { hash } = params[alg]
    const mKey = await crypto.subtle.importKey('raw', key.params.k, { name: 'HMAC', hash }, false, ['sign'])
    const sig = await crypto.subtle.sign('HMAC', mKey, Buffer.from(msg))
    return Buffer.from(sig)
  },

  /**
   * Verifies the signature with the message and key, using the specified
   * algorithm.
   * 
   * @param {String} alg
   * @param {Buffer|String} msg
   * @param {Buffer} sig
   * @param {Key} key
   * @returns {Boolean}
   */
  async verify(alg, msg, sig, key) {
    assertKey(key, alg)

    const { hash } = params[alg]
    const mKey = await crypto.subtle.importKey('raw', key.params.k, { name: 'HMAC', hash }, false, ['verify'])
    return crypto.subtle.verify('HMAC', mKey, sig, Buffer.from(msg))
  }
}

/**
 * Asserts the key is valid.
 * 
 * @param {Key} key 
 * @param {String} alg 
 */
function assertKey(key, alg) {
  if (key.type !== 'oct') {
    throw `Invalid key for ${alg} algorithm`
  }
}

export default HMAC