jose 6.2.11 → 6.2.13

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.
Files changed (85) hide show
  1. package/README.md +2 -2
  2. package/dist/types/index.d.ts +1 -2
  3. package/dist/types/jwe/compact/decrypt.d.ts +9 -12
  4. package/dist/types/jwe/compact/encrypt.d.ts +14 -17
  5. package/dist/types/jwe/flattened/decrypt.d.ts +9 -12
  6. package/dist/types/jwe/flattened/encrypt.d.ts +17 -20
  7. package/dist/types/jwe/general/decrypt.d.ts +12 -17
  8. package/dist/types/jwe/general/encrypt.d.ts +19 -22
  9. package/dist/types/jwk/embedded.d.ts +3 -1
  10. package/dist/types/jwk/thumbprint.d.ts +4 -6
  11. package/dist/types/jwks/local.d.ts +5 -4
  12. package/dist/types/jwks/remote.d.ts +20 -21
  13. package/dist/types/jws/compact/sign.d.ts +7 -6
  14. package/dist/types/jws/compact/verify.d.ts +9 -12
  15. package/dist/types/jws/flattened/sign.d.ts +8 -7
  16. package/dist/types/jws/flattened/verify.d.ts +10 -12
  17. package/dist/types/jws/general/sign.d.ts +16 -17
  18. package/dist/types/jws/general/verify.d.ts +14 -18
  19. package/dist/types/jwt/decrypt.d.ts +15 -11
  20. package/dist/types/jwt/encrypt.d.ts +25 -23
  21. package/dist/types/jwt/sign.d.ts +4 -8
  22. package/dist/types/jwt/unsecured.d.ts +3 -7
  23. package/dist/types/jwt/verify.d.ts +12 -7
  24. package/dist/types/key/export.d.ts +6 -6
  25. package/dist/types/key/generate_key_pair.d.ts +9 -14
  26. package/dist/types/key/generate_secret.d.ts +10 -10
  27. package/dist/types/key/import.d.ts +21 -20
  28. package/dist/types/types.d.ts +217 -254
  29. package/dist/types/util/base64url.d.ts +7 -7
  30. package/dist/types/util/decode_jwt.d.ts +6 -1
  31. package/dist/types/util/decode_protected_header.d.ts +4 -3
  32. package/dist/types/util/errors.d.ts +30 -41
  33. package/dist/webapi/jwe/compact/decrypt.js +1 -2
  34. package/dist/webapi/jwe/compact/encrypt.js +9 -26
  35. package/dist/webapi/jwe/flattened/decrypt.js +3 -3
  36. package/dist/webapi/jwe/flattened/encrypt.js +11 -30
  37. package/dist/webapi/jwe/general/decrypt.js +6 -6
  38. package/dist/webapi/jwe/general/encrypt.js +36 -60
  39. package/dist/webapi/jwk/embedded.js +3 -4
  40. package/dist/webapi/jwk/thumbprint.js +11 -14
  41. package/dist/webapi/jwks/local.js +18 -11
  42. package/dist/webapi/jwks/remote.js +5 -5
  43. package/dist/webapi/jws/compact/sign.js +2 -4
  44. package/dist/webapi/jws/compact/verify.js +2 -2
  45. package/dist/webapi/jws/flattened/sign.js +8 -15
  46. package/dist/webapi/jws/flattened/verify.js +4 -14
  47. package/dist/webapi/jws/general/sign.js +6 -13
  48. package/dist/webapi/jws/general/verify.js +8 -10
  49. package/dist/webapi/jwt/decrypt.js +2 -3
  50. package/dist/webapi/jwt/encrypt.js +13 -27
  51. package/dist/webapi/jwt/sign.js +3 -3
  52. package/dist/webapi/jwt/unsecured.js +4 -5
  53. package/dist/webapi/jwt/verify.js +4 -4
  54. package/dist/webapi/key/export.js +12 -16
  55. package/dist/webapi/key/generate_key_pair.js +4 -13
  56. package/dist/webapi/key/generate_secret.js +5 -5
  57. package/dist/webapi/key/import.js +5 -9
  58. package/dist/webapi/lib/asn1.js +4 -6
  59. package/dist/webapi/lib/buffer_utils.js +39 -4
  60. package/dist/webapi/lib/content_encryption.js +29 -37
  61. package/dist/webapi/lib/deflate.js +9 -19
  62. package/dist/webapi/lib/jwe_algorithms.js +0 -4
  63. package/dist/webapi/lib/jwe_decrypt.js +30 -63
  64. package/dist/webapi/lib/jwe_encrypt.js +27 -60
  65. package/dist/webapi/lib/jws_algorithms.js +2 -2
  66. package/dist/webapi/lib/jws_sign.js +31 -45
  67. package/dist/webapi/lib/jws_verify.js +43 -48
  68. package/dist/webapi/lib/jwt_claims_set.js +45 -44
  69. package/dist/webapi/lib/key.js +122 -62
  70. package/dist/webapi/lib/key_management.js +57 -92
  71. package/dist/webapi/lib/{options.js → validate.js} +64 -3
  72. package/dist/webapi/util/base64url.js +5 -19
  73. package/dist/webapi/util/decode_jwt.js +13 -13
  74. package/dist/webapi/util/decode_protected_header.js +6 -6
  75. package/package.json +1 -1
  76. package/dist/webapi/lib/base64.js +0 -20
  77. package/dist/webapi/lib/crypto_key.js +0 -27
  78. package/dist/webapi/lib/helpers.js +0 -45
  79. package/dist/webapi/lib/invalid_key_input.js +0 -12
  80. package/dist/webapi/lib/is_key_like.js +0 -19
  81. package/dist/webapi/lib/jwk_metadata.js +0 -19
  82. package/dist/webapi/lib/jwk_to_key.js +0 -10
  83. package/dist/webapi/lib/key_options.js +0 -8
  84. package/dist/webapi/lib/signing.js +0 -22
  85. package/dist/webapi/lib/type_checks.js +0 -30
@@ -1,19 +1,22 @@
1
- import { jwkToKey } from "../lib/jwk_to_key.js";
1
+ import { jwkToKey, snapshotJwk } from "../lib/key.js";
2
2
  import { JWS } from "../lib/jws_algorithms.js";
3
3
  import { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys } from "../util/errors.js";
4
- import { isJwkSet } from "../lib/type_checks.js";
5
- import { snapshotJwk } from "../lib/jwk_metadata.js";
4
+ import { isJwkSet } from "../lib/validate.js";
6
5
  function isUsableJWK(jwk, entry, alg, kid) {
7
- const { kty, key_ops, ext, kid: jwkKid, alg: jwkAlg, use, crv } = snapshotJwk(jwk), keyOps = Array.isArray(key_ops) ? [...key_ops] : key_ops;
6
+ const { kty, key_ops: keyOps, ext, kid: jwkKid, alg: jwkAlg, use, crv } = jwk;
8
7
  return (ext === void 0 || typeof ext == "boolean") && (keyOps === void 0 || Array.isArray(keyOps) && keyOps.every((operation, index) => typeof operation == "string" && keyOps.indexOf(operation) === index) && keyOps.includes("verify")) && entry.kty.includes(kty) && (kid === void 0 || typeof kid == "string" && kid === jwkKid) && (jwkAlg === void 0 ? kty !== "AKP" : alg === jwkAlg) && (use === void 0 || use === "sig") && (!entry.crv || crv === entry.crv);
9
8
  }
10
9
  async function importWithAlgCache(cache, jwk, entry) {
11
10
  const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk), { alg } = entry;
12
11
  if (cached[alg] === void 0) {
13
- const key = await jwkToKey(entry, { ...jwk, alg, ext: !0 });
14
- if (key.type !== "public")
15
- throw new JWKSInvalid("JSON Web Key Set members must be public keys");
16
- cached[alg] = key;
12
+ const pending = jwkToKey(entry, jwk, !0).then((key) => {
13
+ if (key.type !== "public")
14
+ throw new JWKSInvalid("JSON Web Key Set members must be public keys");
15
+ return cached[alg] = key, key;
16
+ }).catch((error) => {
17
+ throw cached[alg] === pending && delete cached[alg], error;
18
+ });
19
+ cached[alg] = pending;
17
20
  }
18
21
  return cached[alg];
19
22
  }
@@ -21,16 +24,20 @@ function createLocalJWKSet(jwks) {
21
24
  let snapshot;
22
25
  try {
23
26
  snapshot = structuredClone(jwks);
24
- } catch {
27
+ } catch (cause) {
28
+ throw new JWKSInvalid("JSON Web Key Set malformed", { cause });
25
29
  }
26
30
  if (!isJwkSet(snapshot))
27
31
  throw new JWKSInvalid("JSON Web Key Set malformed");
28
- const cached = /* @__PURE__ */ new WeakMap();
32
+ const metadata = snapshot.keys.map((jwk) => {
33
+ const normalized = snapshotJwk(jwk);
34
+ return Array.isArray(normalized.key_ops) && (normalized.key_ops = [...normalized.key_ops]), normalized;
35
+ }), cached = /* @__PURE__ */ new WeakMap();
29
36
  return Object.defineProperty(async (protectedHeader, token) => {
30
37
  const { alg, kid } = { ...protectedHeader, ...token?.header }, entry = typeof alg == "string" ? JWS[alg] : void 0;
31
38
  if (!entry || entry.secret)
32
39
  throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set');
33
- const candidates = snapshot.keys.filter((jwk2) => isUsableJWK(jwk2, entry, alg, kid)), { 0: jwk, length } = candidates;
40
+ const candidates = snapshot.keys.filter((_, index) => isUsableJWK(metadata[index], entry, alg, kid)), { 0: jwk, length } = candidates;
34
41
  if (!length)
35
42
  throw new JWKSNoMatchingKey();
36
43
  if (length !== 1) {
@@ -1,11 +1,11 @@
1
1
  import { JOSEError, JWKSNoMatchingKey, JWKSTimeout } from "../util/errors.js";
2
2
  import { createLocalJWKSet } from "./local.js";
3
- import { isJwkSet } from "../lib/type_checks.js";
3
+ import { isJwkSet } from "../lib/validate.js";
4
4
  function isCloudflareWorkers() {
5
5
  return typeof WebSocketPair < "u" || typeof navigator < "u" && navigator.userAgent === "Cloudflare-Workers" || typeof EdgeRuntime < "u" && EdgeRuntime === "vercel";
6
6
  }
7
7
  let USER_AGENT;
8
- (typeof navigator > "u" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 ")) && (USER_AGENT = "jose/v6.2.11");
8
+ (typeof navigator > "u" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 ")) && (USER_AGENT = "jose/v6.2.13");
9
9
  const customFetch = /* @__PURE__ */ Symbol();
10
10
  async function fetchJwks(url, headers, signal, fetchImpl = fetch) {
11
11
  const response = await fetchImpl(url, {
@@ -14,14 +14,14 @@ async function fetchJwks(url, headers, signal, fetchImpl = fetch) {
14
14
  redirect: "manual",
15
15
  headers
16
16
  }).catch((err) => {
17
- throw err.name === "TimeoutError" ? new JWKSTimeout() : err;
17
+ throw err.name === "TimeoutError" ? new JWKSTimeout(void 0, { cause: err }) : err;
18
18
  });
19
19
  if (response.status !== 200)
20
20
  throw new JOSEError("Expected 200 OK from the JSON Web Key Set HTTP response");
21
21
  try {
22
22
  return await response.json();
23
- } catch {
24
- throw new JOSEError("Failed to parse the JSON Web Key Set HTTP response as JSON");
23
+ } catch (cause) {
24
+ throw new JOSEError("Failed to parse the JSON Web Key Set HTTP response as JSON", { cause });
25
25
  }
26
26
  }
27
27
  const jwksCache = /* @__PURE__ */ Symbol();
@@ -1,12 +1,10 @@
1
1
  import { createCompactSignature } from "../../lib/jws_sign.js";
2
- import { assertNotSet } from "../../lib/helpers.js";
2
+ import { assertNotSet, assertUint8Array } from "../../lib/validate.js";
3
3
  class CompactSign {
4
4
  #payload;
5
5
  #protectedHeader;
6
6
  constructor(payload) {
7
- if (!(payload instanceof Uint8Array))
8
- throw new TypeError("payload must be an instance of Uint8Array");
9
- this.#payload = payload;
7
+ assertUint8Array(payload, "payload"), this.#payload = payload;
10
8
  }
11
9
  setProtectedHeader(protectedHeader) {
12
10
  return assertNotSet(this.#protectedHeader, "setProtectedHeader"), this.#protectedHeader = protectedHeader, this;
@@ -1,7 +1,7 @@
1
1
  import { prepareVerify, verifyCompact } from "../../lib/jws_verify.js";
2
2
  async function compactVerify(jws, key, options) {
3
- const verified = await verifyCompact(jws, prepareVerify(options), key), result = { payload: verified[0], protectedHeader: verified[1] };
4
- return typeof key == "function" ? { ...result, key: verified[3] } : result;
3
+ const [result] = await verifyCompact(jws, prepareVerify(options), key);
4
+ return result;
5
5
  }
6
6
  export {
7
7
  compactVerify
@@ -1,27 +1,20 @@
1
1
  import { createSignature } from "../../lib/jws_sign.js";
2
- import { assertNotSet } from "../../lib/helpers.js";
2
+ import { assertNotSet, assertUint8Array } from "../../lib/validate.js";
3
3
  class FlattenedSign {
4
- #payload;
5
- #protectedHeader;
6
- #unprotectedHeader;
4
+ #input;
7
5
  constructor(payload) {
8
- if (!(payload instanceof Uint8Array))
9
- throw new TypeError("payload must be an instance of Uint8Array");
10
- this.#payload = payload;
6
+ assertUint8Array(payload, "payload"), this.#input = [payload];
11
7
  }
12
8
  setProtectedHeader(protectedHeader) {
13
- return assertNotSet(this.#protectedHeader, "setProtectedHeader"), this.#protectedHeader = protectedHeader, this;
9
+ return assertNotSet(this.#input[1], "setProtectedHeader"), this.#input[1] = protectedHeader, this;
14
10
  }
15
11
  setUnprotectedHeader(unprotectedHeader) {
16
- return assertNotSet(this.#unprotectedHeader, "setUnprotectedHeader"), this.#unprotectedHeader = unprotectedHeader, this;
12
+ return assertNotSet(this.#input[2], "setUnprotectedHeader"), this.#input[2] = unprotectedHeader, this;
17
13
  }
18
14
  async sign(key, options) {
19
- const [jws] = await createSignature({
20
- payload: this.#payload,
21
- protectedHeader: this.#protectedHeader,
22
- unprotectedHeader: this.#unprotectedHeader,
23
- crit: options?.crit
24
- }, key);
15
+ const input = [...this.#input];
16
+ input[3] = options?.crit;
17
+ const [jws] = await createSignature(input, key);
25
18
  return jws;
26
19
  }
27
20
  }
@@ -1,21 +1,11 @@
1
1
  import { JWSInvalid } from "../../util/errors.js";
2
- import { isObject } from "../../lib/type_checks.js";
3
- import { encodeJsonUnencodedPayload, prepareVerify, snapshotJws, verifySignature, verifyResult } from "../../lib/jws_verify.js";
2
+ import { isObject } from "../../lib/validate.js";
3
+ import { encodeJsonUnencodedPayload, prepareVerify, snapshotJws, verifySignature } from "../../lib/jws_verify.js";
4
4
  async function flattenedVerify(jws, key, options) {
5
5
  if (!isObject(jws))
6
6
  throw new JWSInvalid("Flattened JWS must be an object");
7
- const snapshot = snapshotJws(jws);
8
- if (snapshot.protected === void 0 && snapshot.header === void 0)
9
- throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members');
10
- if (snapshot.protected !== void 0 && typeof snapshot.protected != "string")
11
- throw new JWSInvalid("JWS Protected Header incorrect type");
12
- if (snapshot.payload === void 0)
13
- throw new JWSInvalid("JWS Payload missing");
14
- if (typeof snapshot.signature != "string")
15
- throw new JWSInvalid("JWS Signature missing or incorrect type");
16
- if (snapshot.header !== void 0 && !isObject(snapshot.header))
17
- throw new JWSInvalid("JWS Unprotected Header incorrect type");
18
- return verifyResult(snapshot, await verifySignature(snapshot, prepareVerify(options), key, encodeJsonUnencodedPayload));
7
+ const snapshot = snapshotJws(jws), [result] = await verifySignature(snapshot, prepareVerify(options), key, encodeJsonUnencodedPayload);
8
+ return result;
19
9
  }
20
10
  export {
21
11
  flattenedVerify
@@ -1,6 +1,6 @@
1
1
  import { createSignature } from "../../lib/jws_sign.js";
2
2
  import { JWSInvalid } from "../../util/errors.js";
3
- import { assertNotSet } from "../../lib/helpers.js";
3
+ import { assertNotSet, assertUint8Array } from "../../lib/validate.js";
4
4
  class IndividualSignature {
5
5
  #parent;
6
6
  state;
@@ -36,26 +36,19 @@ class GeneralSign {
36
36
  async sign() {
37
37
  if (!this.#signatures.length)
38
38
  throw new JWSInvalid("at least one signature must be added");
39
- if (!(this.#payload instanceof Uint8Array))
40
- throw new TypeError("payload must be an instance of Uint8Array");
39
+ assertUint8Array(this.#payload, "payload");
41
40
  const jws = {
42
41
  signatures: [],
43
42
  payload: ""
44
- }, encoded = [];
43
+ }, encodedPayloadCache = [];
45
44
  let b64;
46
- for (let i = 0; i < this.#signatures.length; i++) {
47
- const signature = this.#signatures[i], [protectedHeader, unprotectedHeader, key, crit] = signature.state, [{ payload, ...rest }, signatureB64] = await createSignature({
48
- payload: this.#payload,
49
- protectedHeader,
50
- unprotectedHeader,
51
- crit,
52
- encoded
53
- }, key);
45
+ for (const signature of this.#signatures) {
46
+ const [protectedHeader, unprotectedHeader, key, crit] = signature.state, [{ payload, ...signatureMembers }, signatureB64] = await createSignature([this.#payload, protectedHeader, unprotectedHeader, crit, encodedPayloadCache], key);
54
47
  if (b64 === void 0)
55
48
  b64 = signatureB64, jws.payload = payload;
56
49
  else if (b64 !== signatureB64)
57
50
  throw new JWSInvalid("inconsistent use of JWS Unencoded Payload (RFC7797)");
58
- jws.signatures.push(rest);
51
+ jws.signatures.push(signatureMembers);
59
52
  }
60
53
  return jws;
61
54
  }
@@ -1,12 +1,9 @@
1
- import { encodeJsonUnencodedPayload, parseProtectedHeader, prepareVerify, snapshotJws, verifySignature, verifyResult } from "../../lib/jws_verify.js";
1
+ import { encodeJsonUnencodedPayload, parseProtectedHeader, prepareVerify, snapshotJws, verifySignature } from "../../lib/jws_verify.js";
2
2
  import { JWSInvalid, JWSSignatureVerificationFailed } from "../../util/errors.js";
3
- import { isObject } from "../../lib/type_checks.js";
3
+ import { isObject } from "../../lib/validate.js";
4
4
  function snapshotSignature(signature, payload) {
5
5
  try {
6
- const jws = snapshotJws(signature, [payload]), { protected: encodedProtected, header, signature: encodedSignature } = jws;
7
- if (encodedProtected === void 0 && header === void 0 || encodedProtected !== void 0 && typeof encodedProtected != "string" || typeof encodedSignature != "string" || header !== void 0 && !isObject(header))
8
- return;
9
- const protectedHeader = parseProtectedHeader(encodedProtected), { b64, crit } = protectedHeader;
6
+ const jws = snapshotJws(signature, [payload]), protectedHeader = parseProtectedHeader(jws.protected), { b64, crit } = protectedHeader;
10
7
  return [
11
8
  jws,
12
9
  protectedHeader,
@@ -34,13 +31,14 @@ async function generalVerify(jws, key, options) {
34
31
  throw new JWSSignatureVerificationFailed();
35
32
  }
36
33
  const payload = inputPayload instanceof Uint8Array ? new Uint8Array(inputPayload) : inputPayload, candidates = signatureEntries.map((signature) => snapshotSignature(signature, payload)).filter((candidate) => candidate !== void 0);
37
- let modes = 0;
38
- for (const [, , mode] of candidates)
39
- if (modes |= mode, modes === 3)
34
+ let payloadEncodings = 0;
35
+ for (const [, , payloadEncoding] of candidates)
36
+ if (payloadEncodings |= payloadEncoding, payloadEncodings === 3)
40
37
  throw new JWSInvalid("inconsistent use of JWS Unencoded Payload (RFC7797)");
41
38
  for (const candidate of candidates)
42
39
  try {
43
- return verifyResult(candidate[0], await verifySignature(candidate[0], shared, key, encodeJsonUnencodedPayload, candidate[1]));
40
+ const [result] = await verifySignature(candidate[0], shared, key, encodeJsonUnencodedPayload, candidate[1]);
41
+ return result;
44
42
  } catch {
45
43
  }
46
44
  throw new JWSSignatureVerificationFailed();
@@ -2,12 +2,11 @@ import { prepareDecrypt, decryptCompact } from "../lib/jwe_decrypt.js";
2
2
  import { validateClaimsSet } from "../lib/jwt_claims_set.js";
3
3
  import { JWTClaimValidationFailed } from "../util/errors.js";
4
4
  async function jwtDecrypt(jwt, key, options) {
5
- const decrypted = await decryptCompact(jwt, prepareDecrypt(options), key), protectedHeader = decrypted[1], payload = validateClaimsSet(protectedHeader, decrypted[0], options);
5
+ const { plaintext, ...result } = await decryptCompact(jwt, prepareDecrypt(options), key), { protectedHeader } = result, payload = validateClaimsSet(protectedHeader, plaintext, options);
6
6
  for (const claim of ["iss", "sub", "aud"])
7
7
  if (protectedHeader[claim] !== void 0 && (claim === "aud" ? JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud) : protectedHeader[claim] !== payload[claim]))
8
8
  throw new JWTClaimValidationFailed(`replicated "${claim}" claim header parameter mismatch`, payload, claim, "mismatch");
9
- const result = { payload, protectedHeader };
10
- return typeof key == "function" ? { ...result, key: decrypted[2] } : result;
9
+ return { payload, ...result };
11
10
  }
12
11
  export {
13
12
  jwtDecrypt
@@ -1,26 +1,23 @@
1
- import { createJWE } from "../lib/jwe_encrypt.js";
2
- import { JWTClaimsBuilder, jwtClaim, jwtData } from "../lib/jwt_claims_set.js";
3
- import { assertNotSet } from "../lib/helpers.js";
1
+ import { compactJWE, createJWE } from "../lib/jwe_encrypt.js";
2
+ import { JWTClaimsBuilder, jwtClaim, jwtClaimsSetBytes } from "../lib/jwt_claims_set.js";
3
+ import { assertNotSet } from "../lib/validate.js";
4
4
  const EncryptJWT_base = JWTClaimsBuilder;
5
5
  class EncryptJWT extends EncryptJWT_base {
6
- #cek;
7
- #iv;
8
- #keyManagementParameters;
9
- #protectedHeader;
6
+ #input = [void 0];
10
7
  #replicateIssuerAsHeader;
11
8
  #replicateSubjectAsHeader;
12
9
  #replicateAudienceAsHeader;
13
10
  setProtectedHeader(protectedHeader) {
14
- return assertNotSet(this.#protectedHeader, "setProtectedHeader"), this.#protectedHeader = protectedHeader, this;
11
+ return assertNotSet(this.#input[1], "setProtectedHeader"), this.#input[1] = protectedHeader, this;
15
12
  }
16
13
  setKeyManagementParameters(parameters) {
17
- return assertNotSet(this.#keyManagementParameters, "setKeyManagementParameters"), this.#keyManagementParameters = parameters, this;
14
+ return assertNotSet(this.#input[7], "setKeyManagementParameters"), this.#input[7] = parameters, this;
18
15
  }
19
16
  setContentEncryptionKey(cek) {
20
- return assertNotSet(this.#cek, "setContentEncryptionKey"), this.#cek = cek, this;
17
+ return assertNotSet(this.#input[5], "setContentEncryptionKey"), this.#input[5] = cek, this;
21
18
  }
22
19
  setInitializationVector(iv) {
23
- return assertNotSet(this.#iv, "setInitializationVector"), this.#iv = iv, this;
20
+ return assertNotSet(this.#input[6], "setInitializationVector"), this.#input[6] = iv, this;
24
21
  }
25
22
  replicateIssuerAsHeader() {
26
23
  return this.#replicateIssuerAsHeader = !0, this;
@@ -32,26 +29,15 @@ class EncryptJWT extends EncryptJWT_base {
32
29
  return this.#replicateAudienceAsHeader = !0, this;
33
30
  }
34
31
  async encrypt(key, options) {
35
- const plaintext = jwtData(this);
36
- this.#protectedHeader && (this.#replicateIssuerAsHeader || this.#replicateSubjectAsHeader || this.#replicateAudienceAsHeader) && (this.#protectedHeader = {
37
- ...this.#protectedHeader,
32
+ const plaintext = jwtClaimsSetBytes(this);
33
+ this.#input[1] && (this.#replicateIssuerAsHeader || this.#replicateSubjectAsHeader || this.#replicateAudienceAsHeader) && (this.#input[1] = {
34
+ ...this.#input[1],
38
35
  iss: this.#replicateIssuerAsHeader ? jwtClaim(this, "iss") : void 0,
39
36
  sub: this.#replicateSubjectAsHeader ? jwtClaim(this, "sub") : void 0,
40
37
  aud: this.#replicateAudienceAsHeader ? jwtClaim(this, "aud") : void 0
41
38
  });
42
- const jwe = await createJWE([
43
- plaintext,
44
- this.#protectedHeader,
45
- void 0,
46
- void 0,
47
- void 0,
48
- this.#cek,
49
- this.#iv,
50
- this.#keyManagementParameters,
51
- void 0,
52
- !1
53
- ], key, options);
54
- return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join(".");
39
+ const input = [...this.#input];
40
+ return input[0] = plaintext, compactJWE(await createJWE(input, key, options));
55
41
  }
56
42
  }
57
43
  export {
@@ -1,7 +1,7 @@
1
1
  import { createCompactSignature } from "../lib/jws_sign.js";
2
2
  import { JWTInvalid } from "../util/errors.js";
3
- import { JWTClaimsBuilder, jwtData } from "../lib/jwt_claims_set.js";
4
- import { assertNotSet } from "../lib/helpers.js";
3
+ import { JWTClaimsBuilder, jwtClaimsSetBytes } from "../lib/jwt_claims_set.js";
4
+ import { assertNotSet } from "../lib/validate.js";
5
5
  const SignJWT_base = JWTClaimsBuilder;
6
6
  class SignJWT extends SignJWT_base {
7
7
  #protectedHeader;
@@ -9,7 +9,7 @@ class SignJWT extends SignJWT_base {
9
9
  return assertNotSet(this.#protectedHeader, "setProtectedHeader"), this.#protectedHeader = protectedHeader, this;
10
10
  }
11
11
  async sign(key, options) {
12
- return createCompactSignature(jwtData(this), this.#protectedHeader, options?.crit, key, () => {
12
+ return createCompactSignature(jwtClaimsSetBytes(this), this.#protectedHeader, options?.crit, key, () => {
13
13
  throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
14
14
  });
15
15
  }
@@ -1,13 +1,12 @@
1
1
  import * as b64u from "../util/base64url.js";
2
- import { decodeBase64url, parseJoseHeader } from "../lib/helpers.js";
2
+ import { decodeBase64url, parseJoseHeader, JWS_RECOGNIZED, validateB64, validateCrit } from "../lib/validate.js";
3
3
  import { JWSInvalid, JWTInvalid } from "../util/errors.js";
4
- import { validateClaimsSet, JWTClaimsBuilder, jwtData } from "../lib/jwt_claims_set.js";
5
- import { JWS_RECOGNIZED, validateB64, validateCrit } from "../lib/options.js";
4
+ import { validateClaimsSet, JWTClaimsBuilder, jwtClaimsSetBytes } from "../lib/jwt_claims_set.js";
6
5
  const UnsecuredJWT_base = JWTClaimsBuilder;
7
6
  class UnsecuredJWT extends UnsecuredJWT_base {
8
7
  encode() {
9
- const header = b64u.encode(JSON.stringify({ alg: "none" })), payload = b64u.encode(jwtData(this));
10
- return `${header}.${payload}.`;
8
+ const encodedProtectedHeader = b64u.encode(JSON.stringify({ alg: "none" })), encodedPayload = b64u.encode(jwtClaimsSetBytes(this));
9
+ return `${encodedProtectedHeader}.${encodedPayload}.`;
11
10
  }
12
11
  static decode(jwt, options) {
13
12
  if (typeof jwt != "string")
@@ -2,11 +2,11 @@ import { prepareVerify, verifyCompact } from "../lib/jws_verify.js";
2
2
  import { validateClaimsSet } from "../lib/jwt_claims_set.js";
3
3
  import { JWTInvalid } from "../util/errors.js";
4
4
  async function jwtVerify(jwt, key, options) {
5
- const verified = await verifyCompact(jwt, prepareVerify(options), key);
6
- if (!verified[2])
5
+ const [verified, b64] = await verifyCompact(jwt, prepareVerify(options), key);
6
+ if (!b64)
7
7
  throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
8
- const result = { payload: validateClaimsSet(verified[1], verified[0], options), protectedHeader: verified[1] };
9
- return typeof key == "function" ? { ...result, key: verified[3] } : result;
8
+ const payload = validateClaimsSet(verified.protectedHeader, verified.payload, options);
9
+ return { ...verified, payload };
10
10
  }
11
11
  export {
12
12
  jwtVerify
@@ -1,11 +1,13 @@
1
1
  import { toSPKI as exportPublic, toPKCS8 as exportPrivate } from "../lib/asn1.js";
2
- import { invalidKeyInput } from "../lib/invalid_key_input.js";
2
+ import { invalidKeyInput, isCryptoKey, isKeyObject } from "../lib/key.js";
3
3
  import { encode as b64u } from "../util/base64url.js";
4
- import { isCryptoKey, isKeyObject } from "../lib/is_key_like.js";
5
- function omitUndefinedProperties(jwk) {
6
- return Object.fromEntries(Object.entries(jwk).filter(([, value]) => value !== void 0));
4
+ function exportSPKI(key) {
5
+ return exportPublic(key);
6
+ }
7
+ function exportPKCS8(key) {
8
+ return exportPrivate(key);
7
9
  }
8
- async function keyToJWK(key) {
10
+ async function exportJWK(key) {
9
11
  if (isKeyObject(key))
10
12
  if (key.type === "secret")
11
13
  key = key.export();
@@ -20,17 +22,11 @@ async function keyToJWK(key) {
20
22
  throw new TypeError(invalidKeyInput(key, "CryptoKey", "KeyObject", "Uint8Array"));
21
23
  if (!key.extractable)
22
24
  throw new TypeError("non-extractable CryptoKey cannot be exported as a JWK");
23
- const { ext, key_ops, alg, use, ...jwk } = omitUndefinedProperties(await crypto.subtle.exportKey("jwk", key));
24
- return jwk.kty === "AKP" && (jwk.alg = alg), jwk;
25
- }
26
- function exportSPKI(key) {
27
- return exportPublic(key);
28
- }
29
- function exportPKCS8(key) {
30
- return exportPrivate(key);
31
- }
32
- function exportJWK(key) {
33
- return keyToJWK(key);
25
+ const jwk = await crypto.subtle.exportKey("jwk", key);
26
+ delete jwk.ext, delete jwk.key_ops, delete jwk.use, jwk.kty !== "AKP" && delete jwk.alg;
27
+ for (const parameter of Object.keys(jwk))
28
+ jwk[parameter] === void 0 && delete jwk[parameter];
29
+ return jwk;
34
30
  }
35
31
  export {
36
32
  exportJWK,
@@ -1,5 +1,5 @@
1
1
  import { JOSENotSupported } from "../util/errors.js";
2
- import { validateExtractableOption } from "../lib/key_options.js";
2
+ import { validateExtractableOption } from "../lib/key.js";
3
3
  import { keyAlgorithm, unsupportedAlg, algArgument } from "../lib/key_algorithm.js";
4
4
  function getModulusLengthOption(options) {
5
5
  const modulusLength = options?.modulusLength ?? 2048;
@@ -13,18 +13,9 @@ async function generateKeyPair(alg, options) {
13
13
  let algorithm;
14
14
  if (entry.resolve) {
15
15
  const crv = options?.crv ?? "P-256";
16
- switch (crv) {
17
- case "P-256":
18
- case "P-384":
19
- case "P-521":
20
- algorithm = { name: "ECDH", namedCurve: crv };
21
- break;
22
- case "X25519":
23
- algorithm = { name: "X25519" };
24
- break;
25
- default:
26
- throw new JOSENotSupported("Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, and X25519");
27
- }
16
+ if (!["P-256", "P-384", "P-521", "X25519"].includes(crv))
17
+ throw new JOSENotSupported("Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, and X25519");
18
+ algorithm = entry.resolve({ crv });
28
19
  } else {
29
20
  if (entry.crv !== void 0 && options?.crv !== void 0 && options.crv !== entry.crv)
30
21
  throw new JOSENotSupported(`Invalid or unsupported crv option provided, the only supported value for ${alg} is ${entry.crv}`);
@@ -1,13 +1,13 @@
1
1
  import { unsupportedAlg, algArgument } from "../lib/key_algorithm.js";
2
- import { validateExtractableOption } from "../lib/key_options.js";
2
+ import { validateExtractableOption } from "../lib/key.js";
3
3
  async function generateSecret(alg, options) {
4
4
  const extractable = validateExtractableOption(options?.extractable);
5
- let length, algorithm, keyUsages;
5
+ let keyLengthBits, algorithm, keyUsages;
6
6
  switch (alg) {
7
7
  case "HS256":
8
8
  case "HS384":
9
9
  case "HS512":
10
- length = +alg.slice(-3), algorithm = { name: "HMAC", hash: `SHA-${length}`, length }, keyUsages = ["sign", "verify"];
10
+ keyLengthBits = +alg.slice(-3), algorithm = { name: "HMAC", hash: `SHA-${keyLengthBits}`, length: keyLengthBits }, keyUsages = ["sign", "verify"];
11
11
  break;
12
12
  case "A128CBC-HS256":
13
13
  case "A192CBC-HS384":
@@ -16,7 +16,7 @@ async function generateSecret(alg, options) {
16
16
  case "A128KW":
17
17
  case "A192KW":
18
18
  case "A256KW":
19
- length = +alg.slice(1, 4), algorithm = { name: "AES-KW", length }, keyUsages = ["wrapKey", "unwrapKey"];
19
+ keyLengthBits = +alg.slice(1, 4), algorithm = { name: "AES-KW", length: keyLengthBits }, keyUsages = ["wrapKey", "unwrapKey"];
20
20
  break;
21
21
  case "A128GCMKW":
22
22
  case "A192GCMKW":
@@ -24,7 +24,7 @@ async function generateSecret(alg, options) {
24
24
  case "A128GCM":
25
25
  case "A192GCM":
26
26
  case "A256GCM":
27
- length = +alg.slice(1, 4), algorithm = { name: "AES-GCM", length }, keyUsages = ["encrypt", "decrypt"];
27
+ keyLengthBits = +alg.slice(1, 4), algorithm = { name: "AES-GCM", length: keyLengthBits }, keyUsages = ["encrypt", "decrypt"];
28
28
  break;
29
29
  default:
30
30
  unsupportedAlg(algArgument);
@@ -1,11 +1,9 @@
1
1
  import { decode as decodeBase64URL } from "../util/base64url.js";
2
2
  import { fromSPKI, fromPKCS8, fromX509 } from "../lib/asn1.js";
3
- import { jwkToKey } from "../lib/jwk_to_key.js";
3
+ import { jwkToKey, validateExtractableOption, normalizeJwk } from "../lib/key.js";
4
4
  import { keyAlgorithm } from "../lib/key_algorithm.js";
5
5
  import { JOSENotSupported } from "../util/errors.js";
6
- import { isObject } from "../lib/type_checks.js";
7
- import { validateExtractableOption } from "../lib/key_options.js";
8
- import { normalizeJwk } from "../lib/jwk_metadata.js";
6
+ import { isObject } from "../lib/validate.js";
9
7
  async function importSPKI(spki, alg, options) {
10
8
  if (typeof spki != "string" || spki.indexOf("-----BEGIN PUBLIC KEY-----") !== 0)
11
9
  throw new TypeError('"spki" must be SPKI formatted string');
@@ -25,9 +23,7 @@ async function importJWK(jwk, alg, options) {
25
23
  if (!isObject(jwk))
26
24
  throw new TypeError("JWK must be an object");
27
25
  const normalized = normalizeJwk(jwk), extractable = validateExtractableOption(options?.extractable), { alg: jwkAlg } = normalized;
28
- alg ??= jwkAlg;
29
- const ext = extractable ?? normalized.ext;
30
- if (normalized.kty !== "oct" && !alg)
26
+ if (alg ??= jwkAlg, normalized.kty !== "oct" && !alg)
31
27
  throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
32
28
  switch (normalized.kty) {
33
29
  case "oct":
@@ -39,12 +35,12 @@ async function importJWK(jwk, alg, options) {
39
35
  throw new TypeError('missing "alg" (Algorithm) Parameter value');
40
36
  if (alg !== jwkAlg)
41
37
  throw new TypeError("JWK alg and alg option value mismatch");
42
- return jwkToKey(keyAlgorithm(alg), { ...normalized, ext });
38
+ return jwkToKey(keyAlgorithm(alg), normalized, extractable);
43
39
  }
44
40
  case "RSA":
45
41
  case "EC":
46
42
  case "OKP":
47
- return jwkToKey(keyAlgorithm(alg), { ...normalized, alg, ext });
43
+ return jwkToKey(keyAlgorithm(alg), normalized, extractable);
48
44
  default:
49
45
  throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value');
50
46
  }
@@ -1,9 +1,7 @@
1
- import { invalidKeyInput } from "./invalid_key_input.js";
2
- import { encodeBase64, decodeBase64 } from "../lib/base64.js";
1
+ import { invalidKeyInput, isCryptoKey, isKeyObject, validateExtractableOption } from "./key.js";
2
+ import { encodeBase64, decodeBase64 } from "./buffer_utils.js";
3
3
  import { JOSENotSupported } from "../util/errors.js";
4
4
  import { keyAlgorithm, unsupportedAlg, algArgument } from "./key_algorithm.js";
5
- import { isCryptoKey, isKeyObject } from "./is_key_like.js";
6
- import { validateExtractableOption } from "./key_options.js";
7
5
  const formatPEM = (b64, descriptor) => {
8
6
  const newlined = (b64.match(/.{1,64}/g) || []).join(`
9
7
  `);
@@ -96,8 +94,8 @@ const parseECAlgorithmIdentifier = (state) => {
96
94
  try {
97
95
  const state = createASN1State(keyData);
98
96
  parseKeyHeader(state, keyFormat), algorithm = entry.resolve({ crv: parseECAlgorithmIdentifier(state) });
99
- } catch {
100
- throw new JOSENotSupported("Invalid or unsupported key format");
97
+ } catch (cause) {
98
+ throw new JOSENotSupported("Invalid or unsupported key format", { cause });
101
99
  }
102
100
  else
103
101
  algorithm = entry.subtle;