import { toHex } from "@smithy/util-hex-encoding"; import { toUint8Array } from "@smithy/util-utf8"; import { KEY_TYPE_IDENTIFIER, MAX_CACHE_SIZE } from "./constants"; const signingKeyCache = {}; const cacheQueue = []; export const createScope = (shortDate, region, service) => `${shortDate}/${region}/${service}/${KEY_TYPE_IDENTIFIER}`; export const getSigningKey = async (sha256Constructor, credentials, shortDate, region, service) => { const credsHash = await hmac(sha256Constructor, credentials.secretAccessKey, credentials.accessKeyId); const cacheKey = `${shortDate}:${region}:${service}:${toHex(credsHash)}:${credentials.sessionToken}`; if (cacheKey in signingKeyCache) { return signingKeyCache[cacheKey]; } cacheQueue.push(cacheKey); while (cacheQueue.length > MAX_CACHE_SIZE) { delete signingKeyCache[cacheQueue.shift()]; } let key = `AWS4${credentials.secretAccessKey}`; for (const signable of [shortDate, region, service, KEY_TYPE_IDENTIFIER]) { key = await hmac(sha256Constructor, key, signable); } return (signingKeyCache[cacheKey] = key); }; export const clearCredentialCache = () => { cacheQueue.length = 0; Object.keys(signingKeyCache).forEach((cacheKey) => { delete signingKeyCache[cacheKey]; }); }; const hmac = (ctor, secret, data) => { const hash = new ctor(secret); hash.update(toUint8Array(data)); return hash.digest(); };