unjwt 0.8.3 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- import { safeJsonParse, sanitizeObjectCopy, secureRandomBytes, textEncoder } from "./libs/unsecure.mjs";
2
- import { JWTError, assertClaimValidationOptions, assertCritShape, assertCryptoKey, assertPlainObject, assertStringList, base64Parse, base64Stringify, base64UrlParse, base64UrlStringify, concatUint8Arrays, isAsymmetricJWK, isCryptoKey, isCryptoKeyPair, isJWK, isJWKSet, isPlainObject, isPublicJWK, parsePayloadBytes, parsePayloadSegment, uint32be, validateJwtClaims } from "./_jwt-internal.mjs";
3
- import { ECDSA_CURVES, PBES2_ALGORITHMS, aesBitsOf, checkKeyUsage, cryptoKeyCurve, digestUrl, hashBitsOf, inferJWEAllowedAlgorithms, inferJWSAllowedAlgorithms, innerKeyWrapAlg, isAlgorithm, isContentEncryptionAlgorithm, isECDHESAlgorithm, isEd25519Signature, isJWSAlgorithm, isKeyManagementAlgorithm, isPBES2Algorithm, jwsHashOf, lengthOf, modulusLengthOf, namedCurveOf, pbes2HashOf, rsaOaepHashOf, shaBitsOf, unusableKey } from "./digest.mjs";
1
+ import { safeJsonParse, textEncoder } from "./libs/unsecure.mjs";
2
+ import { JWTError, assertClaimValidationOptions, assertCritShape, assertCryptoKey, assertPlainObject, assertStringList, base64Parse, base64Stringify, base64UrlParse, base64UrlStringify, concatUint8Arrays, isCryptoKey, isCryptoKeyPair, isJWK, isJWKSet, isPlainObject, isPublicJWK, parsePayloadBytes, parsePayloadSegment, uint32be, validateJwtClaims } from "./_jwt-internal.mjs";
3
+ import { ECDSA_CURVES, aesBitsOf, checkKeyUsage, cryptoKeyCurve, digestUrl, hashBitsOf, inferJWEAllowedAlgorithms, inferJWSAllowedAlgorithms, innerKeyWrapAlg, isAlgorithm, isContentEncryptionAlgorithm, isECDHESAlgorithm, isEd25519Signature, isJWSAlgorithm, isKeyManagementAlgorithm, isPBES2Algorithm, jwsHashOf, lengthOf, modulusLengthOf, namedCurveOf, pbes2HashOf, rsaOaepHashOf, shaBitsOf, unusableKey } from "./digest.mjs";
4
4
  const MAX_QUOTED_VALUE = 64;
5
5
  function quoteTokenValue(value) {
6
6
  const text = String(value);
@@ -154,7 +154,7 @@ function generateCEK(alg) {
154
154
  }
155
155
  function checkCEKLength(cek, expected) {
156
156
  const actual = cek.byteLength << 3;
157
- if (actual !== expected) throw new JWTError(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`, "ERR_INVALID_OPTION");
157
+ if (actual !== expected) throw new JWTError(`Invalid Content Encryption Key length, expected ${expected} bits (got ${actual})`, "ERR_INVALID_OPTION");
158
158
  }
159
159
  function assertOctKeyLength(bytes, alg) {
160
160
  if (!alg) return;
@@ -446,7 +446,7 @@ function subtleMapping(jwk, alg) {
446
446
  };
447
447
  keyUsages = hasPrivateMember(jwk) ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"];
448
448
  break;
449
- default: throw new JWTError(`Invalid or unsupported JWK "alg" (Algorithm) Parameter value: ${quoteTokenValue(alg)}.`, "ERR_JWK_INVALID");
449
+ default: throw new JWTError(`Invalid JWK "alg" ${quoteTokenValue(alg)}.`, "ERR_JWK_INVALID");
450
450
  }
451
451
  break;
452
452
  case "EC":
@@ -474,7 +474,7 @@ function subtleMapping(jwk, alg) {
474
474
  };
475
475
  keyUsages = hasPrivateMember(jwk) ? ["deriveBits"] : [];
476
476
  break;
477
- default: throw new JWTError(`Invalid or unsupported JWK "alg" (Algorithm) Parameter value: ${quoteTokenValue(alg)}.`, "ERR_JWK_INVALID");
477
+ default: throw new JWTError(`Invalid JWK "alg" ${quoteTokenValue(alg)}.`, "ERR_JWK_INVALID");
478
478
  }
479
479
  break;
480
480
  case "OKP":
@@ -491,10 +491,10 @@ function subtleMapping(jwk, alg) {
491
491
  algorithm = { name: requireCurve(jwk, ["X25519"]) };
492
492
  keyUsages = hasPrivateMember(jwk) ? ["deriveBits"] : [];
493
493
  break;
494
- default: throw new JWTError(`Invalid or unsupported JWK "alg" (Algorithm) Parameter value: ${quoteTokenValue(alg)}.`, "ERR_JWK_INVALID");
494
+ default: throw new JWTError(`Invalid JWK "alg" ${quoteTokenValue(alg)}.`, "ERR_JWK_INVALID");
495
495
  }
496
496
  break;
497
- default: throw new JWTError(`Invalid or unsupported JWK "kty" (Key Type) Parameter value: ${quoteTokenValue(jwk.kty)}.`, "ERR_JWK_INVALID");
497
+ default: throw new JWTError(`Invalid JWK "kty" ${quoteTokenValue(jwk.kty)}.`, "ERR_JWK_INVALID");
498
498
  }
499
499
  return {
500
500
  algorithm,
@@ -503,7 +503,7 @@ function subtleMapping(jwk, alg) {
503
503
  }
504
504
  function requireCurve(jwk, allowed) {
505
505
  const crv = "crv" in jwk ? jwk.crv : void 0;
506
- if (typeof crv !== "string" || !allowed.includes(crv)) throw new JWTError(`Invalid or unsupported JWK "crv" (Curve) Parameter value: ${quoteTokenValue(crv)}. Expected one of: ${allowed.join(", ")}.`, "ERR_JWK_INVALID");
506
+ if (typeof crv !== "string" || !allowed.includes(crv)) throw new JWTError(`Invalid JWK "crv" ${quoteTokenValue(crv)}, expected ${allowed.join(", ")}.`, "ERR_JWK_INVALID");
507
507
  return crv;
508
508
  }
509
509
  function hasPrivateMember(jwk) {
@@ -542,7 +542,7 @@ async function deriveECDHESKey(publicKey, privateKey, algorithm, keyLength, apu
542
542
  function ecdhDerivedBits(alg, enc) {
543
543
  if (alg !== "ECDH-ES") return aesBitsOf(innerKeyWrapAlg(alg));
544
544
  if (enc) return bitLengthCEK(enc);
545
- throw new JWTError("ECDH-ES requires \"enc\", the content encryption algorithm the key is agreed for.", "ERR_JWE_INVALID");
545
+ throw new JWTError("ECDH-ES requires \"enc\" to derive the key.", "ERR_JWE_INVALID");
546
546
  }
547
547
  function generateEphemeralKeyPair(recipientKey) {
548
548
  return crypto.subtle.generateKey(recipientKey.algorithm, true, ["deriveBits"]);
@@ -594,7 +594,7 @@ function assertPBES2Params(params) {
594
594
  }
595
595
  function assertPBES2Salt(salt, name) {
596
596
  if (salt instanceof Uint8Array && salt.length >= 8) return;
597
- throw new JWTError(`${name} must be 8 or more octets (RFC 7518 §4.8.1.1).`, "ERR_INVALID_OPTION");
597
+ throw new JWTError(`${name} must be 8 or more octets.`, "ERR_INVALID_OPTION");
598
598
  }
599
599
  function assertPBES2Count(count, name) {
600
600
  if (typeof count !== "number" || !Number.isInteger(count) || count < 1) throw new JWTError(`${name} must be a positive integer.`, "ERR_INVALID_OPTION");
@@ -696,7 +696,7 @@ async function encryptKey(alg, enc, key, providedCek, providedParameters = {}) {
696
696
  ({encryptedKey, ...parameters} = await gcmkwEncrypt(alg, key, cek, iv));
697
697
  break;
698
698
  }
699
- default: throw new JWTError(`Invalid or unsupported "alg" (JWE Algorithm) header value: ${quoteTokenValue(alg)}`, "ERR_JWE_ALG_NOT_ALLOWED");
699
+ default: throw new JWTError(`Unsupported JWE "alg" ${quoteTokenValue(alg)}`, "ERR_JWE_ALG_NOT_ALLOWED");
700
700
  }
701
701
  return {
702
702
  cek,
@@ -774,21 +774,21 @@ const EC_ECDH_CURVES = /* @__PURE__ */ new Set([
774
774
  const OKP_ECDH_CURVES = /* @__PURE__ */ new Set(["X25519"]);
775
775
  function contentAlgorithm(enc) {
776
776
  if (enc) return enc;
777
- throw new JWTError("ECDH-ES requires \"enc\", the content encryption algorithm the key is agreed for.", "ERR_JWE_INVALID");
777
+ throw new JWTError("ECDH-ES requires \"enc\" to derive the key.", "ERR_JWE_INVALID");
778
778
  }
779
779
  function assertEphemeralCurve(ephemeralKey, recipientKey) {
780
780
  assertECDHKeyAllowed(ephemeralKey);
781
781
  const ephemeralCurve = cryptoKeyCurve(ephemeralKey);
782
782
  const recipientCurve = cryptoKeyCurve(recipientKey);
783
783
  if (ephemeralCurve === recipientCurve) return;
784
- throw new JWTError(`ECDH-ES ephemeral key curve ${quoteTokenValue(ephemeralCurve)} does not match the recipient key curve ${quoteTokenValue(recipientCurve)}.`, "ERR_JWK_INVALID");
784
+ throw new JWTError(`ECDH-ES ephemeral key curve ${quoteTokenValue(ephemeralCurve)} does not match recipient curve ${quoteTokenValue(recipientCurve)}.`, "ERR_JWK_INVALID");
785
785
  }
786
786
  function invalidEpk(detail) {
787
787
  return new JWTError(`Invalid JWE: "epk" ${detail}`, "ERR_JWE_INVALID");
788
788
  }
789
789
  function assertEpkCurve(epkCurve, recipientCurve) {
790
790
  if (!recipientCurve || !epkCurve || epkCurve === recipientCurve) return;
791
- throw invalidEpk(`curve "${epkCurve}" does not match the recipient key curve "${recipientCurve}".`);
791
+ throw invalidEpk(`curve "${epkCurve}" does not match recipient curve "${recipientCurve}".`);
792
792
  }
793
793
  function toPublicEpkJwk(jwk) {
794
794
  const { kty } = jwk;
@@ -863,7 +863,7 @@ const pemBody = (pem, descriptor) => {
863
863
  return pem.slice(bodyStart, bodyEnd).replaceAll(/\s/g, "");
864
864
  };
865
865
  const genericExport = async (keyType, keyFormat, key) => {
866
- if (!isCryptoKey(key)) throw new JWTError(`Key must be of type CryptoKey, got ${typeof key}`, "ERR_INVALID_OPTION");
866
+ if (!isCryptoKey(key)) throw new JWTError("Key must be of type CryptoKey", "ERR_INVALID_OPTION");
867
867
  if (!key.extractable) throw new JWTError("CryptoKey is not extractable", "ERR_JWK_INVALID");
868
868
  if (key.type !== keyType) throw new JWTError(`key is not a ${keyType} key`, "ERR_JWK_INVALID");
869
869
  return formatPEM(base64Stringify(new Uint8Array(await crypto.subtle.exportKey(keyFormat, key))), `${keyType.toUpperCase()} KEY`);
@@ -935,7 +935,7 @@ const genericImport = async (descriptor, keyFormat, pem, alg, options) => {
935
935
  algorithm = { name: requireOKPCurve(keyData, "Ed25519") };
936
936
  keyUsages = isPublic ? ["verify"] : ["sign"];
937
937
  break;
938
- default: throw new JWTError("Invalid or unsupported \"alg\" (Algorithm) value", "ERR_JWK_UNSUPPORTED");
938
+ default: throw new JWTError("Invalid or unsupported \"alg\" value", "ERR_JWK_UNSUPPORTED");
939
939
  }
940
940
  try {
941
941
  return await crypto.subtle.importKey(keyFormat, keyData, algorithm, options?.extractable ?? isPublic, keyUsages);
@@ -1151,7 +1151,7 @@ function assertEntryLimit(count, limit, options) {
1151
1151
  }
1152
1152
  function assertCandidateLimit(count, limit) {
1153
1153
  if (count <= limit) return;
1154
- throw new JWTError(`${count} candidate keys exceed the limit of ${limit}; narrow the JWK Set with a "kid".`, "ERR_JWK_KEY_NOT_FOUND");
1154
+ throw new JWTError(`${count} candidate keys exceed the limit of ${limit}, narrow them with a "kid".`, "ERR_JWK_KEY_NOT_FOUND");
1155
1155
  }
1156
1156
  function assertJWKSetCandidates(candidates, options) {
1157
1157
  if (candidates.length === 0) {
@@ -1199,20 +1199,20 @@ function assertProtectedOnlyOption(header, options) {
1199
1199
  const { tier, family } = options;
1200
1200
  for (const param of PROTECTED_ONLY_PARAMS[family]) {
1201
1201
  if (!Object.hasOwn(header, param)) continue;
1202
- throw new JWTError(`${family} "${param}" must be integrity protected; move it from the ${tier} header to the protected header.`, "ERR_INVALID_OPTION");
1202
+ throw new JWTError(`${family} "${param}" must be in the protected header, not the ${tier} header.`, "ERR_INVALID_OPTION");
1203
1203
  }
1204
1204
  }
1205
1205
  function assertProducerKeyHeaders(header, options) {
1206
1206
  if (!header) return;
1207
1207
  const { tier, family } = options;
1208
- if (Object.hasOwn(header, "jwk") && !isPublicJWK(Reflect.get(header, "jwk"))) throw new JWTError(`${family} "jwk" in the ${tier} header must be a public JWK; pass the pair's publicKey half.`, "ERR_INVALID_OPTION");
1209
- if (Object.hasOwn(header, "epk")) throw new JWTError(`${family} "epk" is written by the ECDH-ES key agreement; pass an ephemeral key through "ecdh.ephemeralKey" instead of the ${tier} header.`, "ERR_INVALID_OPTION");
1208
+ if (Object.hasOwn(header, "jwk") && !isPublicJWK(Reflect.get(header, "jwk"))) throw new JWTError(`${family} "jwk" in the ${tier} header must be a public JWK.`, "ERR_INVALID_OPTION");
1209
+ if (Object.hasOwn(header, "epk")) throw new JWTError(`${family} "epk" is not a header option, use "ecdh.ephemeralKey".`, "ERR_INVALID_OPTION");
1210
1210
  }
1211
1211
  function assertProducerConfirmation(payload) {
1212
1212
  if (typeof payload !== "object" || payload === null) return;
1213
1213
  const cnf = Reflect.get(payload, "cnf");
1214
1214
  if (typeof cnf !== "object" || cnf === null || !Object.hasOwn(cnf, "jwk")) return;
1215
- if (!isPublicJWK(Reflect.get(cnf, "jwk"))) throw new JWTError("Invalid JWT \"cnf\" (Confirmation) Claim: \"jwk\" must be a public JWK (RFC 7800 §3.2).", "ERR_JWT_CLAIM_INVALID");
1215
+ if (!isPublicJWK(Reflect.get(cnf, "jwk"))) throw new JWTError("Invalid JWT \"cnf\": \"jwk\" must be a public JWK.", "ERR_JWT_CLAIM_INVALID");
1216
1216
  }
1217
1217
  function assertOptionEntry(entry, options) {
1218
1218
  const { label, objects } = options;
@@ -1226,12 +1226,12 @@ function assertProducerPartyInfo(name, value) {
1226
1226
  function assertProducerCEK(cek, enc) {
1227
1227
  if (cek === void 0) return;
1228
1228
  const expected = bitLengthCEK(enc) >> 3;
1229
- if (!(cek instanceof Uint8Array) || cek.length !== expected) throw new JWTError(`"cek" must be ${expected} bytes for ${enc} (got ${cek instanceof Uint8Array ? cek.length : typeof cek}).`, "ERR_INVALID_OPTION");
1229
+ if (!(cek instanceof Uint8Array) || cek.length !== expected) throw new JWTError(`"cek" must be ${expected} bytes for ${enc}.`, "ERR_INVALID_OPTION");
1230
1230
  }
1231
1231
  function assertProducerIV(iv, enc) {
1232
1232
  if (iv === void 0) return;
1233
1233
  const expected = bitLengthIV(enc) >> 3;
1234
- if (!(iv instanceof Uint8Array) || iv.length !== expected) throw new JWTError(`"contentEncryptionIV" must be ${expected} bytes for ${enc} (got ${iv instanceof Uint8Array ? iv.length : typeof iv}).`, "ERR_INVALID_OPTION");
1234
+ if (!(iv instanceof Uint8Array) || iv.length !== expected) throw new JWTError(`"contentEncryptionIV" must be ${expected} bytes for ${enc}.`, "ERR_INVALID_OPTION");
1235
1235
  }
1236
1236
  function assertConsumerOptions(options) {
1237
1237
  assertOptionEntry(options, {
@@ -1320,7 +1320,7 @@ function buildECDHAgreementParams(ecdh) {
1320
1320
  }
1321
1321
  async function resolveSigningKey(alg, key, usage) {
1322
1322
  if (key instanceof Uint8Array) {
1323
- if (alg !== "HS256" && alg !== "HS384" && alg !== "HS512") throw new JWTError(`Raw key bytes are HMAC secrets; ${alg} needs an asymmetric key. Pass a JWK or a CryptoKey.`, "ERR_JWK_INVALID");
1323
+ if (alg !== "HS256" && alg !== "HS384" && alg !== "HS512") throw new JWTError(`${alg} needs an asymmetric key, not raw bytes.`, "ERR_JWK_INVALID");
1324
1324
  assertOctKeyLength(key, alg);
1325
1325
  return crypto.subtle.importKey("raw", key, {
1326
1326
  name: "HMAC",
@@ -1348,13 +1348,13 @@ function resolvePayloadMode(options) {
1348
1348
  let mode = payload ?? "json";
1349
1349
  if (forceUint8Array !== void 0) {
1350
1350
  if (payload === void 0) mode = forceUint8Array ? "bytes" : "json";
1351
- else if (forceUint8Array !== (payload === "bytes")) throw new JWTError("\"forceUint8Array\" contradicts \"payload\"; pass \"payload\" alone.", "ERR_INVALID_OPTION");
1351
+ else if (forceUint8Array !== (payload === "bytes")) throw new JWTError("\"forceUint8Array\" contradicts \"payload\", pass \"payload\" alone.", "ERR_INVALID_OPTION");
1352
1352
  }
1353
1353
  if (validateClaims === true && mode !== "json") throw new JWTError("\"validateClaims\" requires payload: \"json\".", "ERR_INVALID_OPTION");
1354
1354
  return mode;
1355
1355
  }
1356
1356
  function stringKeyError() {
1357
- return new JWTError("String keys are not accepted: pass an oct JWK or a Uint8Array secret, or import PEM text with importPEM().", "ERR_JWK_INVALID");
1357
+ return new JWTError("Key must be a JWK, CryptoKey or Uint8Array, not a string.", "ERR_JWK_INVALID");
1358
1358
  }
1359
1359
  function assertNotStringKey(key) {
1360
1360
  if (typeof key === "string") throw stringKeyError();
@@ -1383,7 +1383,7 @@ function checkAlgAllowed(alg, key, options) {
1383
1383
  if (algorithms !== void 0) return algorithms.includes(alg) ? void 0 : notAllowed(alg, ctx);
1384
1384
  if (isJWK(key) && typeof key.alg === "string" && (!ctx.octRoles || key.kty !== "oct")) return key.alg === alg || isEd25519Signature(key.alg) && isEd25519Signature(alg) ? void 0 : notAllowed(alg, ctx);
1385
1385
  const inferred = ctx.infer(key, { allowSymmetric });
1386
- if (!inferred) return new JWTError(`Cannot infer allowed ${ctx.label.toLowerCase()}s from this key; pass "options.algorithms" explicitly.`, ctx.errorCode);
1386
+ if (!inferred) return new JWTError("Cannot infer allowed algorithms from this key, pass \"algorithms\".", ctx.errorCode);
1387
1387
  return inferred.includes(alg) ? void 0 : notAllowed(alg, ctx);
1388
1388
  }
1389
1389
  function notAllowed(alg, ctx) {
@@ -1415,14 +1415,14 @@ function checkJWSAlgSupported(alg) {
1415
1415
  });
1416
1416
  }
1417
1417
  function checkJWSB64(header) {
1418
- if (Object.hasOwn(header, "b64") && typeof header.b64 !== "boolean") return new JWTError("Invalid JWS: \"b64\" must be a boolean (RFC 7797 §3).", "ERR_JWS_INVALID");
1418
+ if (Object.hasOwn(header, "b64") && typeof header.b64 !== "boolean") return new JWTError("Invalid JWS: \"b64\" must be a boolean.", "ERR_JWS_INVALID");
1419
1419
  if (header.b64 !== false) return void 0;
1420
1420
  if (Array.isArray(header.crit) && header.crit.includes("b64")) return void 0;
1421
- return new JWTError("Invalid JWS: \"b64\" must be listed in \"crit\" (RFC 7797 §6).", "ERR_JWS_INVALID");
1421
+ return new JWTError("Invalid JWS: \"b64\" must be listed in \"crit\".", "ERR_JWS_INVALID");
1422
1422
  }
1423
1423
  function assertB64Option(header) {
1424
1424
  if (!header || !Object.hasOwn(header, "b64") || typeof header.b64 === "boolean") return;
1425
- throw new JWTError("\"b64\" must be a boolean (RFC 7797 §3).", "ERR_INVALID_OPTION");
1425
+ throw new JWTError("\"b64\" must be a boolean.", "ERR_INVALID_OPTION");
1426
1426
  }
1427
1427
  function applyB64Header(header) {
1428
1428
  assertB64Option(header);
@@ -1493,7 +1493,7 @@ const JWE_ENC_CEK_FORMAT = /* @__PURE__ */ Object.freeze({
1493
1493
  function assertDirectKeyRole(key, enc) {
1494
1494
  if (!isJWK(key) || typeof key.alg !== "string" || key.alg === "dir") return;
1495
1495
  if (enc !== void 0 && key.alg === enc) return;
1496
- throw new JWTError(`JWK "alg" is "${key.alg}" but "dir" requires a key declared as "dir" or as the token's "enc" (${enc ?? "unknown"}).`, "ERR_JWK_INVALID");
1496
+ throw new JWTError(`JWK "alg" is "${key.alg}" but "dir" requires "dir" or the token's "enc".`, "ERR_JWK_INVALID");
1497
1497
  }
1498
1498
  const JWE_DIRECT_ALGS = /* @__PURE__ */ new Set(["dir", "ECDH-ES"]);
1499
1499
  function checkJWEAlgSupported(alg) {
@@ -1568,11 +1568,11 @@ function checkJWEZip(header) {
1568
1568
  }
1569
1569
  function assertNoZipOption(header, tier) {
1570
1570
  if (!header || !Object.hasOwn(header, "zip")) return;
1571
- throw new JWTError(`JWE compression ("zip") is not supported; remove it from the ${tier} header.`, "ERR_INVALID_OPTION");
1571
+ throw new JWTError(`JWE compression ("zip") in the ${tier} header is not supported.`, "ERR_INVALID_OPTION");
1572
1572
  }
1573
1573
  function checkJWEUnprotectedCrit(header) {
1574
1574
  if (!header || !Object.hasOwn(header, "crit")) return void 0;
1575
- return new JWTError("Invalid JWE: \"crit\" must be integrity protected (RFC 7516 §4.1.13).", "ERR_JWE_INVALID");
1575
+ return new JWTError("Invalid JWE: \"crit\" must be integrity protected.", "ERR_JWE_INVALID");
1576
1576
  }
1577
1577
  function typMatches(expected, actual) {
1578
1578
  if (typeof actual !== "string") return false;
@@ -1584,7 +1584,7 @@ function checkProtectedTyp(expected, protectedHeader, options) {
1584
1584
  if (typMatches(expected, actual)) return void 0;
1585
1585
  const { family, label } = options;
1586
1586
  const where = label ? ` on ${label}` : "";
1587
- const message = actual === void 0 ? `Invalid ${family}: the protected header${where} carries no "typ"; expected "${expected}".` : `Invalid ${family}: "typ" (Type) Header Parameter mismatch${where}. Expected "${expected}", got ${JSON.stringify(actual)}.`;
1587
+ const message = actual === void 0 ? `Invalid ${family}: the protected header${where} carries no "typ", expected "${expected}".` : `Invalid ${family}: "typ" mismatch${where}, expected "${expected}".`;
1588
1588
  return new JWTError(message, `ERR_${family}_INVALID`);
1589
1589
  }
1590
1590
  function normalizeTyp(typ) {
@@ -1654,111 +1654,6 @@ const RSA_SIGNATURE_ALGORITHMS = /* @__PURE__ */ new Set([
1654
1654
  "PS384",
1655
1655
  "PS512"
1656
1656
  ]);
1657
- async function generateKey(alg, options = {}) {
1658
- const exportToJWK = options.toJWK !== void 0 && options.toJWK;
1659
- const defaultExtractable = exportToJWK || options.extractable !== false;
1660
- const kid = exportToJWK ? assertKidOption(options.kid) : void 0;
1661
- if (alg === "A128CBC-HS256" || alg === "A192CBC-HS384" || alg === "A256CBC-HS512") {
1662
- const keyLength = bitLengthCEK(alg);
1663
- const keyBytes = secureRandomBytes(keyLength >> 3);
1664
- if (exportToJWK) {
1665
- const jwk = await keyToJWK(keyBytes);
1666
- const keyOps = options.keyUsage === void 0 ? void 0 : resolveKeyUsage(options.keyUsage, {
1667
- allowed: CONTENT_ENCRYPTION_USAGES,
1668
- fallback: ["encrypt", "decrypt"],
1669
- alg
1670
- });
1671
- return withGeneratedKid(kid, withKeyOps({
1672
- ...jwk,
1673
- alg
1674
- }, keyOps));
1675
- }
1676
- return keyBytes;
1677
- }
1678
- const { algorithm, keyUsages } = getGenerateKeyParams(alg, options);
1679
- const key = await crypto.subtle.generateKey(algorithm, defaultExtractable, keyUsages);
1680
- if (exportToJWK) {
1681
- if (isCryptoKeyPair(key)) {
1682
- const pairAlg = generatedPairAlgorithm(alg);
1683
- const [pub, priv] = await Promise.all([exportJWK(key.publicKey), exportJWK(key.privateKey)]);
1684
- const publicKey = await withGeneratedKid(kid, withKeyOps(withAlg(pub, pairAlg), requestedKeyOps(options, key.publicKey)));
1685
- const named = publicKey.kid === void 0 ? void 0 : { kid: publicKey.kid };
1686
- return {
1687
- privateKey: {
1688
- ...withKeyOps(withAlg(priv, pairAlg), requestedKeyOps(options, key.privateKey)),
1689
- ...named
1690
- },
1691
- publicKey
1692
- };
1693
- }
1694
- return withGeneratedKid(kid, withKeyOps(withAlg(await exportJWK(key), generatedSecretAlgorithm(alg)), requestedKeyOps(options, key)));
1695
- }
1696
- return key;
1697
- }
1698
- async function generateJWK(alg, options) {
1699
- const { keyUsage, modulusLength, publicExponent, namedCurve, kid, extractable: _extractable, toJWK: _toJWK, ...jwkParams } = options ?? {};
1700
- assertNoReservedJWKParams(jwkParams);
1701
- const result = await generateKey(alg, {
1702
- keyUsage,
1703
- modulusLength,
1704
- publicExponent,
1705
- namedCurve,
1706
- kid,
1707
- toJWK: true
1708
- });
1709
- if (result && typeof result === "object" && "privateKey" in result && "publicKey" in result) return {
1710
- privateKey: {
1711
- ...jwkParams,
1712
- ...result.privateKey
1713
- },
1714
- publicKey: {
1715
- ...jwkParams,
1716
- ...result.publicKey
1717
- }
1718
- };
1719
- return {
1720
- ...jwkParams,
1721
- ...result
1722
- };
1723
- }
1724
- async function deriveKeyFromPassword(password, options) {
1725
- assertPlainObject(options, "options");
1726
- if (typeof password !== "string" && !(password instanceof Uint8Array)) throw new JWTError("\"password\" must be a string or a Uint8Array.", "ERR_INVALID_OPTION");
1727
- const { alg, salt, iterations, extractable, keyUsage } = options;
1728
- assertPBES2Algorithm(alg);
1729
- const exportToJWK = options.toJWK !== void 0 && options.toJWK;
1730
- const saltBytes = typeof salt === "string" ? textEncoder.encode(salt) : salt;
1731
- assertPBES2Salt(saltBytes, "\"salt\"");
1732
- assertPBES2Count(iterations, "\"iterations\"");
1733
- const derivedBytes = await deriveKey(saltBytes, alg, iterations, typeof password === "string" ? textEncoder.encode(password) : password);
1734
- const wrappingAlg = innerKeyWrapAlg(alg);
1735
- const finalUsages = keyUsage ?? ["wrapKey", "unwrapKey"];
1736
- const finalExtractable = exportToJWK ? true : extractable === true;
1737
- const derivedKey = await crypto.subtle.importKey("raw", derivedBytes, { name: "AES-KW" }, finalExtractable, finalUsages);
1738
- if (exportToJWK) return withKeyOps({
1739
- ...await keyToJWK(derivedKey),
1740
- alg: wrappingAlg,
1741
- kty: "oct"
1742
- }, requestedKeyOps(options, derivedKey));
1743
- return derivedKey;
1744
- }
1745
- async function deriveJWKFromPassword(password, options) {
1746
- assertPlainObject(options, "options");
1747
- const { alg, salt, iterations, keyUsage, kid: kidOption, extractable: _extractable, toJWK: _toJWK, ...jwkParams } = options;
1748
- assertNoReservedJWKParams(jwkParams);
1749
- const kid = assertKidOption(kidOption);
1750
- const result = await deriveKeyFromPassword(password, {
1751
- alg,
1752
- salt,
1753
- iterations,
1754
- keyUsage,
1755
- toJWK: true
1756
- });
1757
- return {
1758
- ...jwkParams,
1759
- ...await withGeneratedKid(kid, result)
1760
- };
1761
- }
1762
1657
  var WeakMapJWKCache = class {
1763
1658
  _map = /* @__PURE__ */ new WeakMap();
1764
1659
  get(jwk, alg) {
@@ -1843,609 +1738,9 @@ function assertIntentOnCryptoKey(key, expect) {
1843
1738
  if (expect === "public" && key.type === "private") throw new JWTError("Private CryptoKey passed where a public key is expected.", "ERR_JWK_INVALID");
1844
1739
  if (expect === "private" && key.type === "public") throw new JWTError("Public CryptoKey passed where a private key is expected.", "ERR_JWK_INVALID");
1845
1740
  }
1846
- async function exportJWK(key, jwkParams) {
1847
- if (!isCryptoKey(key)) throw new JWTError(`exportJWK expects a CryptoKey, got ${key === null ? "null" : typeof key}.`, "ERR_INVALID_OPTION");
1848
- if (!key.extractable) throw new JWTError("A non-extractable CryptoKey cannot be exported as a JWK.", "ERR_JWK_INVALID");
1849
- const exportedJwk = await keyToJWK(key);
1850
- if (jwkParams) {
1851
- const extraParams = sanitizeObjectCopy(jwkParams);
1852
- assertNoReservedJWKParams(extraParams);
1853
- return {
1854
- ...exportedJwk,
1855
- ...extraParams
1856
- };
1857
- }
1858
- return exportedJwk;
1859
- }
1860
- async function exportKey(key, jwkParams) {
1861
- return exportJWK(key, jwkParams);
1862
- }
1863
- function toPublicJWK(jwk) {
1864
- if (!isAsymmetricJWK(jwk)) throw new JWTError(isJWK(jwk) ? "An oct JWK has no public half." : "toPublicJWK expects an asymmetric JWK.", "ERR_JWK_INVALID");
1865
- const { d: _d, p: _p, q: _q, dp: _dp, dq: _dq, qi: _qi, oth: _oth, key_ops, ...publicMembers } = sanitizeObjectCopy({ ...jwk });
1866
- const publicKey = key_ops === void 0 ? publicMembers : {
1867
- ...publicMembers,
1868
- key_ops: publicKeyOps(key_ops)
1869
- };
1870
- if (!isPublicJWK(publicKey)) throw new JWTError(`${jwk.kty} JWK lacks the public members of its key type.`, "ERR_JWK_INVALID");
1871
- return publicKey;
1872
- }
1873
- async function wrapKey(keyToWrap, wrappingKey, options) {
1874
- assertPlainObject(options, "options");
1875
- assertKeyBytesArg(keyToWrap, "keyToWrap");
1876
- const { alg } = options;
1877
- const cekBytes = keyToWrap instanceof Uint8Array ? keyToWrap : new Uint8Array(await crypto.subtle.exportKey("raw", keyToWrap));
1878
- if (alg.endsWith("KW")) assertWrappableCEK(cekBytes, alg);
1879
- if (alg.startsWith("PBES2")) assertPBES2Params({
1880
- p2s: options.p2s,
1881
- p2c: options.p2c
1882
- });
1883
- const importedWrappingKey = await importKey(resolvePasswordKey(alg, wrappingKey), {
1884
- alg,
1885
- expect: "public"
1886
- });
1887
- switch (alg) {
1888
- case "dir": return { encryptedKey: /* @__PURE__ */ new Uint8Array(0) };
1889
- case "A128KW":
1890
- case "A192KW":
1891
- case "A256KW": return { encryptedKey: await aesKwWrap(alg, importedWrappingKey, cekBytes) };
1892
- case "PBES2-HS256+A128KW":
1893
- case "PBES2-HS384+A192KW":
1894
- case "PBES2-HS512+A256KW": {
1895
- const { p2s, p2c } = options;
1896
- if (!p2s || typeof p2c !== "number") throw new JWTError("PBES2 requires 'p2s' (salt) and 'p2c' (count) options", "ERR_JWE_INVALID");
1897
- return pbes2Wrap(alg, importedWrappingKey, cekBytes, p2c, p2s);
1898
- }
1899
- case "A128GCMKW":
1900
- case "A192GCMKW":
1901
- case "A256GCMKW": {
1902
- const { encryptedKey, iv, tag } = await gcmkwEncrypt(alg, importedWrappingKey, cekBytes, options.iv);
1903
- return {
1904
- encryptedKey,
1905
- iv,
1906
- tag
1907
- };
1908
- }
1909
- case "RSA-OAEP":
1910
- case "RSA-OAEP-256":
1911
- case "RSA-OAEP-384":
1912
- case "RSA-OAEP-512":
1913
- assertCryptoKeyFor(alg, importedWrappingKey, "wrapping");
1914
- return { encryptedKey: await encryptRSAES(alg, importedWrappingKey, cekBytes) };
1915
- case "ECDH-ES":
1916
- case "ECDH-ES+A128KW":
1917
- case "ECDH-ES+A192KW":
1918
- case "ECDH-ES+A256KW": {
1919
- assertCryptoKeyFor(alg, importedWrappingKey, "wrapping");
1920
- const enc = options.ecdh?.enc;
1921
- if (enc !== void 0) assertJWEEncSupported(enc);
1922
- if (alg === "ECDH-ES" && !enc) throw new JWTError("ECDH-ES direct key agreement requires options.ecdh.enc (the target content encryption algorithm)", "ERR_JWK_INVALID");
1923
- const { encryptedKey, parameters } = await ecdhesWrap(alg, {
1924
- enc,
1925
- recipientKey: importedWrappingKey,
1926
- cek: cekBytes,
1927
- parameters: buildECDHAgreementParams(options.ecdh)
1928
- });
1929
- const wrapResult = {
1930
- encryptedKey: encryptedKey ?? /* @__PURE__ */ new Uint8Array(0),
1931
- epk: parameters.epk
1932
- };
1933
- if (parameters.apu) wrapResult.apu = parameters.apu;
1934
- if (parameters.apv) wrapResult.apv = parameters.apv;
1935
- return wrapResult;
1936
- }
1937
- default: throw new JWTError(`Unsupported key wrapping algorithm: ${alg}`, "ERR_JWK_UNSUPPORTED");
1938
- }
1939
- }
1940
- async function unwrapKey(wrappedKey, unwrappingKey, options) {
1941
- assertPlainObject(options, "options");
1942
- if (!(wrappedKey instanceof Uint8Array)) throw new JWTError("\"wrappedKey\" must be a Uint8Array.", "ERR_INVALID_OPTION");
1943
- const { alg } = options;
1944
- const returnRaw = options.format === "raw";
1945
- const defaultExtractable = options.extractable !== false;
1946
- const importedUnwrappingKey = await importKey(resolvePasswordKey(alg, unwrappingKey), {
1947
- alg,
1948
- expect: "private"
1949
- });
1950
- let unwrappedCekBytes;
1951
- switch (alg) {
1952
- case "dir":
1953
- assertDirectKeyRole(unwrappingKey, options.enc);
1954
- if (importedUnwrappingKey instanceof Uint8Array) {
1955
- assertOctKeyLength(importedUnwrappingKey, options.enc);
1956
- unwrappedCekBytes = importedUnwrappingKey;
1957
- } else {
1958
- if (!returnRaw) return importedUnwrappingKey;
1959
- unwrappedCekBytes = new Uint8Array(await crypto.subtle.exportKey("raw", importedUnwrappingKey));
1960
- }
1961
- break;
1962
- case "A128KW":
1963
- case "A192KW":
1964
- case "A256KW":
1965
- unwrappedCekBytes = await unwrapping(aesKwUnwrap(alg, importedUnwrappingKey, wrappedKey));
1966
- break;
1967
- case "PBES2-HS256+A128KW":
1968
- case "PBES2-HS384+A192KW":
1969
- case "PBES2-HS512+A256KW": {
1970
- const { p2s, p2c, minIterations, maxIterations } = options;
1971
- if (!p2s || typeof p2c !== "number") throw new JWTError("PBES2 requires 'p2s' (salt) and 'p2c' (count) options", "ERR_JWE_INVALID");
1972
- unwrappedCekBytes = await unwrapping(pbes2Unwrap(alg, importedUnwrappingKey, wrappedKey, p2c, segmentBytes(p2s, "p2s"), minIterations, maxIterations));
1973
- break;
1974
- }
1975
- case "A128GCMKW":
1976
- case "A192GCMKW":
1977
- case "A256GCMKW": {
1978
- if (!options.iv || !options.tag) throw new JWTError("AES-GCMKW requires 'iv' and 'tag' options for unwrapping", "ERR_JWE_INVALID");
1979
- const ivBytes = segmentBytes(options.iv, "iv");
1980
- const tagBytes = segmentBytes(options.tag, "tag");
1981
- assertKeyWrapSegmentLength("iv", ivBytes, bitLengthIV(alg) >> 3, alg);
1982
- assertKeyWrapSegmentLength("tag", tagBytes, bitLengthTag(alg) >> 3, alg);
1983
- unwrappedCekBytes = await unwrapping(gcmkwDecrypt(alg, importedUnwrappingKey, wrappedKey, ivBytes, tagBytes));
1984
- break;
1985
- }
1986
- case "RSA-OAEP":
1987
- case "RSA-OAEP-256":
1988
- case "RSA-OAEP-384":
1989
- case "RSA-OAEP-512": {
1990
- assertCryptoKeyFor(alg, importedUnwrappingKey, "unwrapping");
1991
- unwrappedCekBytes = await unwrapping(decryptRSAES(alg, importedUnwrappingKey, wrappedKey));
1992
- if (returnRaw) break;
1993
- const inferredAlgorithm = options.unwrappedKeyAlgorithm || inferAesImportAlgorithm(options.enc, unwrappedCekBytes.length);
1994
- if (!inferredAlgorithm) throw new JWTError("Unable to infer algorithm for RSA-OAEP unwrapped key. Provide \"unwrappedKeyAlgorithm\" in options.", "ERR_JWE_INVALID");
1995
- const keyUsages = options.keyUsage || ["encrypt", "decrypt"];
1996
- return await crypto.subtle.importKey("raw", unwrappedCekBytes, inferredAlgorithm, defaultExtractable, keyUsages);
1997
- }
1998
- case "ECDH-ES":
1999
- case "ECDH-ES+A128KW":
2000
- case "ECDH-ES+A192KW":
2001
- case "ECDH-ES+A256KW": {
2002
- if (!options.epk) throw new JWTError("ECDH-ES requires 'epk' (Ephemeral Public Key) option", "ERR_JWE_INVALID");
2003
- assertCryptoKeyFor(alg, importedUnwrappingKey, "unwrapping");
2004
- assertECDHKeyAllowed(importedUnwrappingKey);
2005
- const epkCandidate = await normalizeEpk(options.epk, {
2006
- alg,
2007
- recipientKey: importedUnwrappingKey
2008
- });
2009
- const apuBytes = segmentBytes(options.apu ?? /* @__PURE__ */ new Uint8Array(0), "apu");
2010
- const apvBytes = segmentBytes(options.apv ?? /* @__PURE__ */ new Uint8Array(0), "apv");
2011
- assertPartyInfoLength("apu", apuBytes);
2012
- assertPartyInfoLength("apv", apvBytes);
2013
- if (options.enc !== void 0) assertJWEEncSupported(options.enc);
2014
- const infoAlg = alg === "ECDH-ES" ? options.enc : alg;
2015
- if (!infoAlg) throw new JWTError("ECDH-ES requires content encryption algorithm ('enc') to derive the shared secret", "ERR_JWE_INVALID");
2016
- const sharedSecret = await unwrapping(deriveECDHESKey(epkCandidate, importedUnwrappingKey, infoAlg, ecdhDerivedBits(alg, options.enc), apuBytes, apvBytes));
2017
- if (alg === "ECDH-ES") unwrappedCekBytes = sharedSecret;
2018
- else {
2019
- const kwAlg = innerKeyWrapAlg(alg);
2020
- if (!(wrappedKey instanceof Uint8Array) || wrappedKey.length === 0) throw new JWTError("ECDH-ES key agreement with key wrapping requires an encrypted key", "ERR_JWE_INVALID");
2021
- unwrappedCekBytes = await unwrapping(aesKwUnwrap(kwAlg, sharedSecret, wrappedKey));
2022
- }
2023
- break;
2024
- }
2025
- default: throw new JWTError(`Unsupported key unwrapping algorithm: ${alg}`, "ERR_JWK_UNSUPPORTED");
2026
- }
2027
- if (returnRaw) return unwrappedCekBytes;
2028
- return await crypto.subtle.importKey("raw", unwrappedCekBytes, options.unwrappedKeyAlgorithm || { name: "AES-GCM" }, defaultExtractable, options.keyUsage || ["encrypt", "decrypt"]);
2029
- }
2030
- async function importPEM(pem, alg, options) {
2031
- if (typeof pem !== "string") throw new JWTError(`"pem" must be a PEM-encoded string, got ${pem === null ? "null" : typeof pem}.`, "ERR_INVALID_OPTION");
2032
- if (options !== void 0) assertPlainObject(options, "options");
2033
- const extractable = true;
2034
- const pemType = options?.pemType ?? inferPEMType(pem);
2035
- if (!pemType) throw new JWTError("Cannot infer PEM type from the input; pass \"options.pemType\" explicitly.", "ERR_JWK_INVALID");
2036
- let cryptoKey;
2037
- switch (pemType) {
2038
- case "pkcs8":
2039
- cryptoKey = await fromPKCS8(pem, alg, { extractable });
2040
- break;
2041
- case "spki":
2042
- cryptoKey = await fromSPKI(pem, alg, { extractable });
2043
- break;
2044
- case "x509":
2045
- cryptoKey = await fromX509(pem, alg, { extractable });
2046
- break;
2047
- default: throw new JWTError(`Unsupported PEM type: ${String(pemType)}`, "ERR_JWK_UNSUPPORTED");
2048
- }
2049
- return {
2050
- ...await exportJWK(cryptoKey, options?.jwkParams),
2051
- alg
2052
- };
2053
- }
2054
- async function exportPEM(jwk, options) {
2055
- assertPlainObject(jwk, "jwk");
2056
- if (options !== void 0) assertPlainObject(options, "options");
2057
- if (jwk.kty === "oct") throw new JWTError("Octet (symmetric) JWKs (kty: 'oct') cannot be exported to PKCS8 or SPKI PEM formats.", "ERR_JWK_UNSUPPORTED");
2058
- const effectiveAlg = jwk.alg || options?.alg;
2059
- if (!effectiveAlg && (jwk.kty === "RSA" || jwk.kty === "EC" || jwk.kty === "OKP")) throw new JWTError("Algorithm (alg) must be provided in the JWK or via options for converting this JWK type to a CryptoKey.", "ERR_JWK_INVALID");
2060
- if (effectiveAlg !== void 0 && !PEM_ALGORITHMS.has(effectiveAlg)) throw new JWTError(`Unsupported PEM algorithm: ${effectiveAlg}`, "ERR_JWK_UNSUPPORTED");
2061
- const pemFormat = options?.pemFormat ?? ("d" in jwk ? "pkcs8" : "spki");
2062
- const cryptoKeyCandidate = await importKey({
2063
- ...jwk,
2064
- ext: true
2065
- }, {
2066
- alg: effectiveAlg,
2067
- expect: pemFormat === "pkcs8" ? "private" : "public",
2068
- extractable: true
2069
- });
2070
- if (!isCryptoKey(cryptoKeyCandidate)) throw new JWTError("Failed to convert JWK to a CryptoKey instance suitable for PEM export.", "ERR_JWK_INVALID");
2071
- const cryptoKey = cryptoKeyCandidate;
2072
- switch (pemFormat) {
2073
- case "pkcs8":
2074
- if (cryptoKey.type !== "private") throw new JWTError(`Only 'private' type CryptoKeys can be exported to PKCS8 PEM format. Key type is '${cryptoKey.type}'.`, "ERR_JWK_INVALID");
2075
- return toPKCS8(cryptoKey);
2076
- case "spki":
2077
- if (cryptoKey.type !== "public") throw new JWTError(`Only 'public' type CryptoKeys can be exported to SPKI PEM format. Key type is '${cryptoKey.type}'.`, "ERR_JWK_INVALID");
2078
- return toSPKI(cryptoKey);
2079
- default: throw new JWTError(`Unsupported PEM format: ${String(pemFormat)}`, "ERR_JWK_UNSUPPORTED");
2080
- }
2081
- }
2082
- function inferPEMType(pem) {
2083
- if (pem.includes("-----BEGIN PRIVATE KEY-----")) return "pkcs8";
2084
- if (pem.includes("-----BEGIN PUBLIC KEY-----")) return "spki";
2085
- if (pem.includes("-----BEGIN CERTIFICATE-----")) return "x509";
2086
- }
2087
- async function deriveSharedSecret(publicKey, privateKey, options) {
2088
- assertPlainObject(options, "options");
2089
- const { enc: alg, keyLength: requestedKeyLength, partyUInfo, partyVInfo } = options;
2090
- if (!isECDHESAlgorithm(alg)) assertJWEEncSupported(alg);
2091
- if (requestedKeyLength !== void 0) assertDerivedKeyLength(requestedKeyLength);
2092
- const importAlg = isECDHESAlgorithm(alg) ? alg : "ECDH-ES";
2093
- const pubCryptoKey = isCryptoKey(publicKey) ? publicKey : await importKey(publicKey, {
2094
- alg: importAlg,
2095
- expect: "public"
2096
- });
2097
- const privCryptoKey = isCryptoKey(privateKey) ? privateKey : await importKey(privateKey, {
2098
- alg: importAlg,
2099
- expect: "private"
2100
- });
2101
- let keyLength;
2102
- if (requestedKeyLength !== void 0) keyLength = requestedKeyLength;
2103
- else if (alg === "ECDH-ES") throw new JWTError("deriveSharedSecret with enc \"ECDH-ES\" requires an explicit keyLength in options", "ERR_JWK_INVALID");
2104
- else if (isECDHESAlgorithm(alg)) keyLength = aesBitsOf(innerKeyWrapAlg(alg));
2105
- else keyLength = bitLengthCEK(alg);
2106
- return deriveECDHESKey(pubCryptoKey, privCryptoKey, alg, keyLength, partyUInfo ?? /* @__PURE__ */ new Uint8Array(0), partyVInfo ?? /* @__PURE__ */ new Uint8Array(0));
2107
- }
2108
1741
  function getJWKsFromSet(jwkSet, filter) {
2109
1742
  if (!jwkSet || !isJWKSet(jwkSet)) throw new JWTError("Invalid JWK Set provided", "ERR_JWK_INVALID");
2110
1743
  const keys = jwkSet.keys.filter((key) => isJWK(key));
2111
1744
  return filter ? keys.filter(filter) : keys;
2112
1745
  }
2113
- function getGenerateKeyParams(alg, options) {
2114
- let algorithm;
2115
- let keyUsages;
2116
- const requested = options?.keyUsage;
2117
- const usage = (allowed, fallback) => resolveKeyUsage(requested, {
2118
- allowed,
2119
- fallback,
2120
- alg
2121
- });
2122
- const pairUsage = (allowed, fallback) => assertPairUsages(usage(allowed, fallback), {
2123
- fallback,
2124
- alg
2125
- });
2126
- switch (alg) {
2127
- case "HS256":
2128
- case "HS384":
2129
- case "HS512":
2130
- algorithm = {
2131
- name: "HMAC",
2132
- hash: jwsHashOf(alg)
2133
- };
2134
- keyUsages = usage(SIGNATURE_USAGES, ["sign", "verify"]);
2135
- break;
2136
- case "RS256":
2137
- case "RS384":
2138
- case "RS512":
2139
- algorithm = {
2140
- name: "RSASSA-PKCS1-v1_5",
2141
- modulusLength: assertModulusLength(options?.modulusLength),
2142
- publicExponent: assertPublicExponent(options?.publicExponent),
2143
- hash: jwsHashOf(alg)
2144
- };
2145
- keyUsages = pairUsage(SIGNATURE_USAGES, ["sign", "verify"]);
2146
- break;
2147
- case "PS256":
2148
- case "PS384":
2149
- case "PS512":
2150
- algorithm = {
2151
- name: "RSA-PSS",
2152
- modulusLength: assertModulusLength(options?.modulusLength),
2153
- publicExponent: assertPublicExponent(options?.publicExponent),
2154
- hash: jwsHashOf(alg)
2155
- };
2156
- keyUsages = pairUsage(SIGNATURE_USAGES, ["sign", "verify"]);
2157
- break;
2158
- case "RSA-OAEP":
2159
- case "RSA-OAEP-256":
2160
- case "RSA-OAEP-384":
2161
- case "RSA-OAEP-512":
2162
- algorithm = {
2163
- name: "RSA-OAEP",
2164
- modulusLength: assertModulusLength(options?.modulusLength),
2165
- publicExponent: assertPublicExponent(options?.publicExponent),
2166
- hash: rsaOaepHashOf(alg)
2167
- };
2168
- keyUsages = pairUsage(KEY_ENCRYPTION_USAGES, [
2169
- "encrypt",
2170
- "decrypt",
2171
- "wrapKey",
2172
- "unwrapKey"
2173
- ]);
2174
- break;
2175
- case "A128KW":
2176
- case "A192KW":
2177
- case "A256KW":
2178
- algorithm = {
2179
- name: "AES-KW",
2180
- length: aesBitsOf(alg)
2181
- };
2182
- keyUsages = usage(KEY_WRAPPING_USAGES, ["wrapKey", "unwrapKey"]);
2183
- break;
2184
- case "A128GCM":
2185
- case "A192GCM":
2186
- case "A256GCM":
2187
- case "A128GCMKW":
2188
- case "A192GCMKW":
2189
- case "A256GCMKW":
2190
- algorithm = {
2191
- name: "AES-GCM",
2192
- length: aesBitsOf(alg)
2193
- };
2194
- keyUsages = usage(KEY_ENCRYPTION_USAGES, ["encrypt", "decrypt"]);
2195
- break;
2196
- case "ES256":
2197
- case "ES384":
2198
- case "ES512": {
2199
- const namedCurve = ECDSA_CURVES[alg];
2200
- assertNamedCurve(options?.namedCurve, namedCurve, alg);
2201
- algorithm = {
2202
- name: "ECDSA",
2203
- namedCurve
2204
- };
2205
- keyUsages = pairUsage(SIGNATURE_USAGES, ["sign", "verify"]);
2206
- break;
2207
- }
2208
- case "Ed25519":
2209
- assertNamedCurve(options?.namedCurve, "Ed25519", alg);
2210
- keyUsages = pairUsage(SIGNATURE_USAGES, ["sign", "verify"]);
2211
- algorithm = { name: "Ed25519" };
2212
- break;
2213
- case "EdDSA": {
2214
- keyUsages = pairUsage(SIGNATURE_USAGES, ["sign", "verify"]);
2215
- const namedCurve = options?.namedCurve ?? "Ed25519";
2216
- if (namedCurve !== "Ed25519") throw new JWTError("Unsupported namedCurve provided. Supported values are: Ed25519", "ERR_JWK_UNSUPPORTED");
2217
- algorithm = { name: namedCurve };
2218
- break;
2219
- }
2220
- case "ECDH-ES":
2221
- case "ECDH-ES+A128KW":
2222
- case "ECDH-ES+A192KW":
2223
- case "ECDH-ES+A256KW": {
2224
- keyUsages = pairUsage(DERIVATION_USAGES, ["deriveBits"]);
2225
- const namedCurve = options?.namedCurve ?? "P-256";
2226
- switch (namedCurve) {
2227
- case "P-256":
2228
- case "P-384":
2229
- case "P-521":
2230
- algorithm = {
2231
- name: "ECDH",
2232
- namedCurve
2233
- };
2234
- break;
2235
- case "X25519":
2236
- algorithm = { name: "X25519" };
2237
- break;
2238
- default: throw new JWTError("Unsupported namedCurve provided. Supported values are: P-256, P-384, P-521 and X25519", "ERR_JWK_UNSUPPORTED");
2239
- }
2240
- break;
2241
- }
2242
- default: throw new JWTError(`Unsupported or invalid algorithm for key generation: ${alg}`, "ERR_JWK_UNSUPPORTED");
2243
- }
2244
- return {
2245
- algorithm,
2246
- keyUsages
2247
- };
2248
- }
2249
- function inferAesImportAlgorithm(enc, cekLengthBytes) {
2250
- const bitLength = cekLengthBytes << 3;
2251
- if (enc) {
2252
- if (enc.includes("GCM")) return {
2253
- name: "AES-GCM",
2254
- length: aesBitsOf(enc)
2255
- };
2256
- if (enc.includes("CBC-HS")) return;
2257
- }
2258
- if (bitLength === 128 || bitLength === 192 || bitLength === 256) return {
2259
- name: "AES-GCM",
2260
- length: bitLength
2261
- };
2262
- }
2263
- const RESERVED_JWK_PARAMS = /* @__PURE__ */ new Set([
2264
- "kty",
2265
- "alg",
2266
- "key_ops",
2267
- "ext",
2268
- "k",
2269
- "d",
2270
- "n",
2271
- "e",
2272
- "p",
2273
- "q",
2274
- "dp",
2275
- "dq",
2276
- "qi",
2277
- "oth",
2278
- "x",
2279
- "y",
2280
- "crv"
2281
- ]);
2282
- function assertNoReservedJWKParams(jwkParams) {
2283
- const reserved = Object.keys(jwkParams).filter((name) => RESERVED_JWK_PARAMS.has(name));
2284
- if (reserved.length > 0) throw new JWTError(`jwkParams must not set reserved JWK members: ${reserved.join(", ")}`, "ERR_INVALID_OPTION");
2285
- }
2286
- function assertNamedCurve(requested, expected, alg) {
2287
- if (requested === void 0 || requested === expected) return;
2288
- throw new JWTError(`"namedCurve" ${requested} contradicts ${alg}, which is defined over ${expected}.`, "ERR_INVALID_OPTION");
2289
- }
2290
- function assertPublicExponent(publicExponent) {
2291
- if (publicExponent === void 0) return new Uint8Array([
2292
- 1,
2293
- 0,
2294
- 1
2295
- ]);
2296
- if (!(publicExponent instanceof Uint8Array) || publicExponent.length === 0) throw new JWTError("\"publicExponent\" must be the exponent's big-endian bytes as a Uint8Array.", "ERR_INVALID_OPTION");
2297
- return publicExponent;
2298
- }
2299
- const SIGNATURE_USAGES = ["sign", "verify"];
2300
- const KEY_WRAPPING_USAGES = ["wrapKey", "unwrapKey"];
2301
- const KEY_ENCRYPTION_USAGES = [
2302
- "encrypt",
2303
- "decrypt",
2304
- "wrapKey",
2305
- "unwrapKey"
2306
- ];
2307
- const DERIVATION_USAGES = ["deriveBits", "deriveKey"];
2308
- const CONTENT_ENCRYPTION_USAGES = ["encrypt", "decrypt"];
2309
- function resolveKeyUsage(requested, options) {
2310
- const { allowed, fallback, alg } = options;
2311
- if (requested === void 0) return fallback;
2312
- if (!Array.isArray(requested) || requested.length === 0) throw new JWTError("\"keyUsage\" must be a non-empty array.", "ERR_INVALID_OPTION");
2313
- const rejected = requested.filter((entry) => !allowed.includes(entry));
2314
- if (rejected.length > 0) throw new JWTError(`"keyUsage" ${rejected.join(", ")} cannot be served by ${alg}; it admits ${allowed.join(", ")}.`, "ERR_INVALID_OPTION");
2315
- return requested;
2316
- }
2317
- const PRIVATE_KEY_USAGES = [
2318
- "sign",
2319
- "decrypt",
2320
- "unwrapKey",
2321
- "deriveBits",
2322
- "deriveKey"
2323
- ];
2324
- const PUBLIC_KEY_USAGES = [
2325
- "verify",
2326
- "encrypt",
2327
- "wrapKey"
2328
- ];
2329
- function assertPairUsages(usages, options) {
2330
- const { fallback, alg } = options;
2331
- for (const [half, side] of [[PRIVATE_KEY_USAGES, "private"], [PUBLIC_KEY_USAGES, "public"]]) {
2332
- const wanted = fallback.filter((entry) => half.includes(entry));
2333
- if (wanted.length === 0 || usages.some((entry) => half.includes(entry))) continue;
2334
- throw new JWTError(`"keyUsage" leaves the ${side} half of a ${alg} key pair with no usage; include one of ${wanted.join(", ")}.`, "ERR_INVALID_OPTION");
2335
- }
2336
- return usages;
2337
- }
2338
- function assertKidOption(kid) {
2339
- if (kid === void 0 || kid === false || typeof kid === "string") return kid;
2340
- throw new JWTError("\"kid\" must be a string or false.", "ERR_INVALID_OPTION");
2341
- }
2342
- async function withGeneratedKid(kid, jwk) {
2343
- if (kid === false) return jwk;
2344
- return {
2345
- ...jwk,
2346
- kid: kid ?? await thumbprint(jwk)
2347
- };
2348
- }
2349
- const PEM_ALGORITHMS = /* @__PURE__ */ new Set(Object.keys({
2350
- "PS256": true,
2351
- "PS384": true,
2352
- "PS512": true,
2353
- "RS256": true,
2354
- "RS384": true,
2355
- "RS512": true,
2356
- "RSA-OAEP": true,
2357
- "RSA-OAEP-256": true,
2358
- "RSA-OAEP-384": true,
2359
- "RSA-OAEP-512": true,
2360
- "ES256": true,
2361
- "ES384": true,
2362
- "ES512": true,
2363
- "ECDH-ES": true,
2364
- "ECDH-ES+A128KW": true,
2365
- "ECDH-ES+A192KW": true,
2366
- "ECDH-ES+A256KW": true,
2367
- "Ed25519": true,
2368
- "EdDSA": true
2369
- }));
2370
- function assertWrappableCEK(cek, alg) {
2371
- if (cek.length >= 16 && cek.length % 8 === 0) return;
2372
- throw new JWTError(`${alg} wraps a key of 16 or more bytes in whole 8-byte blocks (got ${cek.length}).`, "ERR_INVALID_OPTION");
2373
- }
2374
- async function unwrapping(operation) {
2375
- try {
2376
- return await operation;
2377
- } catch (error) {
2378
- throw asDecryptionError(error);
2379
- }
2380
- }
2381
- function assertPBES2Algorithm(alg) {
2382
- if (typeof alg === "string" && PBES2_ALGORITHMS.includes(alg)) return;
2383
- throw new JWTError(`Password derivation is defined for ${PBES2_ALGORITHMS.join(", ")}, not ${String(alg)}.`, "ERR_JWK_UNSUPPORTED");
2384
- }
2385
- function assertKeyBytesArg(value, name) {
2386
- if (value instanceof Uint8Array || isCryptoKey(value)) return;
2387
- throw new JWTError(`"${name}" must be a Uint8Array or a CryptoKey, got ${value === null ? "null" : typeof value}.`, "ERR_INVALID_OPTION");
2388
- }
2389
- function assertModulusLength(modulusLength) {
2390
- const length = modulusLength ?? 2048;
2391
- if (!Number.isInteger(length) || length < 2048) throw new JWTError("modulusLength must be at least 2048 bits (RFC 7518 §3.3)", "ERR_INVALID_OPTION");
2392
- return length;
2393
- }
2394
- function assertPartyInfoLength(name, bytes) {
2395
- if (bytes.length > 1024) throw new JWTError(`Invalid JWE: "${name}" must not exceed ${MAX_PARTY_INFO_BYTES} bytes (got ${bytes.length}).`, "ERR_JWE_INVALID");
2396
- }
2397
- function assertKeyWrapSegmentLength(name, bytes, expected, alg) {
2398
- if (bytes.length !== expected) throw new JWTError(`Invalid JWE: "${name}" must be ${expected} bytes for ${alg} (got ${bytes.length}).`, "ERR_JWE_INVALID");
2399
- }
2400
- function assertDerivedKeyLength(keyLength) {
2401
- if (!Number.isInteger(keyLength) || keyLength <= 0 || keyLength % 8 !== 0 || keyLength > 8192) throw new JWTError(`keyLength must be a positive multiple of 8 no greater than 8192 bits, got ${keyLength}`, "ERR_INVALID_OPTION");
2402
- }
2403
- function assertCryptoKeyFor(alg, key, role) {
2404
- if (isCryptoKey(key)) return;
2405
- throw new JWTError(`${alg.startsWith("RSA") ? "RSA-OAEP" : "ECDH-ES"} requires the ${role} key to be a CryptoKey`, "ERR_JWK_INVALID");
2406
- }
2407
- function segmentBytes(value, name) {
2408
- return typeof value === "string" ? decodeSegment(value, {
2409
- family: "JWE",
2410
- what: `"${name}"`
2411
- }) : value;
2412
- }
2413
- function withAlg(jwk, alg) {
2414
- return {
2415
- ...jwk,
2416
- alg
2417
- };
2418
- }
2419
- function generatedPairAlgorithm(alg) {
2420
- return alg;
2421
- }
2422
- function generatedSecretAlgorithm(alg) {
2423
- return alg;
2424
- }
2425
- const PUBLIC_KEY_OPS = /* @__PURE__ */ new Map([
2426
- ["sign", "verify"],
2427
- ["verify", "verify"],
2428
- ["decrypt", "encrypt"],
2429
- ["encrypt", "encrypt"],
2430
- ["unwrapKey", "wrapKey"],
2431
- ["wrapKey", "wrapKey"]
2432
- ]);
2433
- function publicKeyOps(keyOps) {
2434
- if (!Array.isArray(keyOps)) return [];
2435
- const ops = [];
2436
- for (const op of keyOps) {
2437
- const publicOp = typeof op === "string" ? PUBLIC_KEY_OPS.get(op) : void 0;
2438
- if (publicOp !== void 0 && !ops.includes(publicOp)) ops.push(publicOp);
2439
- }
2440
- return ops;
2441
- }
2442
- function requestedKeyOps(options, key) {
2443
- return options.keyUsage === void 0 ? void 0 : [...key.usages];
2444
- }
2445
- function withKeyOps(jwk, keyOps) {
2446
- return keyOps === void 0 ? jwk : {
2447
- ...jwk,
2448
- key_ops: keyOps
2449
- };
2450
- }
2451
- export { DEFAULT_JOSE_LIMITS, DEFAULT_PBES2_ITERATIONS, JWE_ALG_CTX, JWE_DIRECT_ALGS, JWS_ALG_CTX, WeakMapJWKCache, applyB64Header, asDecryptionError, asJWTError, asKeyLookupError, asKeyUsageError, assertB64Option, assertCompactToken, assertConsumerOptions, assertDirectKeyRole, assertEntryLimit, assertJWEAlgSupported, assertJWEEncSupported, assertJWKSetCandidates, assertJWSAlgSupported, assertNoZipOption, assertNotStringKey, assertOptionEntry, assertPBES2Params, assertProducerCEK, assertProducerConfirmation, assertProducerCrit, assertProducerIV, assertProducerKeyHeaders, assertProtectedOnlyOption, assertSerializationObject, buildECDHAgreementParams, buildJWKSetFilter, buildUnwrapKeyOptions, checkAlgAllowed, checkJWEAlgSupported, checkJWEContentSegments, checkJWEDirectEncryptedKey, checkJWEEncAllowed, checkJWEEncSupported, checkJWEUnprotectedCrit, checkJWEZip, checkJWSAlgSupported, checkJWSB64, checkProtectedTyp, checkSerializationEntry, clearJWKCache, configureJWKCache, createPBES2Budget, decodeJWEPayload, decodeJWSPayload, decodeProtectedHeader, decodeSegment, decrypt, deriveJWKFromPassword, deriveKeyFromPassword, deriveSharedSecret, encrypt, encryptKey, exportJWK, exportKey, exportPEM, exportReturnedCek, generateCEK, generateIV, generateJWK, generateKey, getJWKsFromSet, importKey, importPEM, isJWEAlgSupported, keyMatchesHeader, quoteTokenValue, resolveKeyInput, resolveLimit, resolvePasswordKey, resolvePayloadMode, resolveSigningKey, serializeProtectedHeader, sign, stringKeyError, thumbprint, toPublicJWK, unwrapKey, validateClaimsIfJson, verify, wrapKey };
1746
+ export { DEFAULT_JOSE_LIMITS, DEFAULT_PBES2_ITERATIONS, JWE_ALG_CTX, JWE_DIRECT_ALGS, JWS_ALG_CTX, MAX_PARTY_INFO_BYTES, WeakMapJWKCache, aesKwUnwrap, aesKwWrap, applyB64Header, asDecryptionError, asJWTError, asKeyLookupError, asKeyUsageError, assertB64Option, assertCompactToken, assertConsumerOptions, assertDirectKeyRole, assertECDHKeyAllowed, assertEntryLimit, assertJWEAlgSupported, assertJWEEncSupported, assertJWKSetCandidates, assertJWSAlgSupported, assertNoZipOption, assertNotStringKey, assertOctKeyLength, assertOptionEntry, assertPBES2Count, assertPBES2Params, assertPBES2Salt, assertProducerCEK, assertProducerConfirmation, assertProducerCrit, assertProducerIV, assertProducerKeyHeaders, assertProtectedOnlyOption, assertSerializationObject, bitLengthCEK, bitLengthIV, bitLengthTag, buildECDHAgreementParams, buildJWKSetFilter, buildUnwrapKeyOptions, checkAlgAllowed, checkJWEAlgSupported, checkJWEContentSegments, checkJWEDirectEncryptedKey, checkJWEEncAllowed, checkJWEEncSupported, checkJWEUnprotectedCrit, checkJWEZip, checkJWSAlgSupported, checkJWSB64, checkProtectedTyp, checkSerializationEntry, clearJWKCache, configureJWKCache, createPBES2Budget, decodeJWEPayload, decodeJWSPayload, decodeProtectedHeader, decodeSegment, decrypt, decryptRSAES, deriveECDHESKey, deriveKey, ecdhDerivedBits, ecdhesWrap, encrypt, encryptKey, encryptRSAES, exportReturnedCek, fromPKCS8, fromSPKI, fromX509, gcmkwDecrypt, gcmkwEncrypt, generateCEK, generateIV, getJWKsFromSet, importKey, isJWEAlgSupported, keyMatchesHeader, keyToJWK, normalizeEpk, pbes2Unwrap, pbes2Wrap, quoteTokenValue, resolveKeyInput, resolveLimit, resolvePasswordKey, resolvePayloadMode, resolveSigningKey, serializeProtectedHeader, sign, stringKeyError, thumbprint, toPKCS8, toSPKI, validateClaimsIfJson, verify };