{"version":3,"file":"encryption.mjs","names":[],"sources":["../../../../../src/modules/kms/jwk/alg/encryption.ts"],"sourcesContent":["import { TypedArrayEncoder } from '../../../../utils'\nimport { KeyManagementError } from '../../error/KeyManagementError'\nimport { getJwkHumanDescription } from '../humanDescription'\nimport type { KnownJwaContentEncryptionAlgorithm, KnownJwaKeyEncryptionAlgorithm } from '../jwa'\nimport type { KmsJwkPrivate, KmsJwkPublic } from '../knownJwk'\nimport type { KmsJwkPublicOct } from '../kty/oct/octJwk'\n\nexport function supportedEncryptionAlgsForKey(jwk: KmsJwkPrivate | Exclude<KmsJwkPublic, KmsJwkPublicOct>) {\n  const algs: Array<KnownJwaContentEncryptionAlgorithm | KnownJwaKeyEncryptionAlgorithm> = []\n\n  // Only symmetric (oct) keys can be used directly for content encryption\n  if (jwk.kty === 'oct') {\n    const keyBits = TypedArrayEncoder.fromBase64Url(jwk.k).length * 8\n\n    // For CBC-HMAC composite algorithms we need exact key sizes\n    if (keyBits === 256) algs.push('A128CBC-HS256')\n    if (keyBits === 384) algs.push('A192CBC-HS384')\n    if (keyBits === 512) algs.push('A256CBC-HS512')\n\n    // For GCM/CBC we just need the exact AES key size\n    if (keyBits === 128) algs.push('A128GCM', 'A128CBC', 'A128KW')\n    if (keyBits === 192) algs.push('A192GCM', 'A192KW')\n    if (keyBits === 256) algs.push('A256GCM', 'A256CBC', 'A256KW', 'C20P', 'XC20P')\n  }\n\n  return algs\n}\n\n/**\n * Get the allowed content encryption algs for a key. If takes all the known supported\n * algs and will filter these based on the optional `alg` key in the JWK.\n *\n * This does not handle the intended key `use` and `key_ops`.\n */\nexport function allowedEncryptionAlgsForKey(\n  jwk: KmsJwkPrivate | Exclude<KmsJwkPublic, KmsJwkPublicOct>\n): Array<KnownJwaContentEncryptionAlgorithm | KnownJwaKeyEncryptionAlgorithm> {\n  const supportedAlgs = supportedEncryptionAlgsForKey(jwk)\n  const allowedAlg = jwk.alg\n\n  return !allowedAlg\n    ? // If no `alg` specified on jwk, return all supported algs\n      supportedAlgs\n    : // If `alg` is specified and supported, return the allowed alg\n      allowedAlg && supportedAlgs.includes(allowedAlg as KnownJwaContentEncryptionAlgorithm)\n      ? [allowedAlg as KnownJwaContentEncryptionAlgorithm | KnownJwaKeyEncryptionAlgorithm]\n      : // Otherwise nothing is allowed (`alg` is specified but not supported)\n        []\n}\n\nexport function assertAllowedEncryptionAlgForKey(\n  jwk: KmsJwkPrivate | Exclude<KmsJwkPublic, KmsJwkPublicOct>,\n  algorithm: KnownJwaContentEncryptionAlgorithm | KnownJwaKeyEncryptionAlgorithm\n) {\n  const allowedAlgs = allowedEncryptionAlgsForKey(jwk)\n  if (!allowedAlgs.includes(algorithm)) {\n    const allowedAlgsText =\n      allowedAlgs.length > 0 ? ` Allowed algs are ${allowedAlgs.map((alg) => `'${alg}'`).join(', ')}` : ''\n    throw new KeyManagementError(\n      `${getJwkHumanDescription(\n        jwk\n      )} cannot be used with algorithm '${algorithm}' for content encryption or decryption.${allowedAlgsText}`\n    )\n  }\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,8BAA8B,KAA6D;CACzG,MAAM,OAAmF,EAAE;AAG3F,KAAI,IAAI,QAAQ,OAAO;EACrB,MAAM,UAAU,kBAAkB,cAAc,IAAI,EAAE,CAAC,SAAS;AAGhE,MAAI,YAAY,IAAK,MAAK,KAAK,gBAAgB;AAC/C,MAAI,YAAY,IAAK,MAAK,KAAK,gBAAgB;AAC/C,MAAI,YAAY,IAAK,MAAK,KAAK,gBAAgB;AAG/C,MAAI,YAAY,IAAK,MAAK,KAAK,WAAW,WAAW,SAAS;AAC9D,MAAI,YAAY,IAAK,MAAK,KAAK,WAAW,SAAS;AACnD,MAAI,YAAY,IAAK,MAAK,KAAK,WAAW,WAAW,UAAU,QAAQ,QAAQ;;AAGjF,QAAO;;;;;;;;AAST,SAAgB,4BACd,KAC4E;CAC5E,MAAM,gBAAgB,8BAA8B,IAAI;CACxD,MAAM,aAAa,IAAI;AAEvB,QAAO,CAAC,aAEJ,gBAEA,cAAc,cAAc,SAAS,WAAiD,GACpF,CAAC,WAAkF,GAEnF,EAAE;;AAGV,SAAgB,iCACd,KACA,WACA;CACA,MAAM,cAAc,4BAA4B,IAAI;AACpD,KAAI,CAAC,YAAY,SAAS,UAAU,EAAE;EACpC,MAAM,kBACJ,YAAY,SAAS,IAAI,qBAAqB,YAAY,KAAK,QAAQ,IAAI,IAAI,GAAG,CAAC,KAAK,KAAK,KAAK;AACpG,QAAM,IAAI,mBACR,GAAG,uBACD,IACD,CAAC,kCAAkC,UAAU,yCAAyC,kBACxF"}