const enc = new TextEncoder('utf-8') async function sign (secret, body) { const algorithm = { name: 'HMAC', hash: 'SHA-384' } const key = await crypto.subtle.importKey('raw', enc.encode(secret), algorithm, false, ['sign', 'verify']) const signature = await crypto.subtle.sign(algorithm.name, key, enc.encode(body)) return `sha384:${Array.from(new Uint8Array(signature), x => x.toString(16).padStart(2, '0')).join('')}` } function getExpiration (future) { return new Date(Date.now() + future) .toISOString() .replace('T', ' ') .replace(/\.\d+Z$/, '+00:00') } /** * Adds an expiration date and signs the params object if a secret is passed to * it. If no secret is given, it returns the same object. * * @param {string | undefined} secret * @param {object} params * @returns {Promise<{ params: string, signature?: string }>} */ export default async function generateSignatureIfSecret (secret, params) { let signature if (secret) { // eslint-disable-next-line no-param-reassign params.auth.expires = getExpiration(5 * 60 * 1000) // eslint-disable-next-line no-param-reassign params = JSON.stringify(params) signature = await sign(secret, params) } return { params, signature } }