unjwt 0.6.1 → 0.7.1

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,4 +1,3 @@
1
- //#region src/core/types/jwk.d.ts
2
1
  /**
3
2
  * The decoded JOSE protected header received by a {@link JWKLookupFunction}.
4
3
  *
@@ -28,8 +27,12 @@ type JWKLookupFunctionHeader = {
28
27
  *
29
28
  * Returning a `string` is meaningful for JWE only (PBES2 password); for JWS
30
29
  * a string return is encoded to bytes and used as a raw symmetric key.
30
+ *
31
+ * The optional `TReturn` generic lets callers who always hand back a specific
32
+ * key shape (e.g. a `JWK_EC_Public<"ES256">`) preserve that narrowing all the
33
+ * way into the `verify` / `decrypt` key resolution path.
31
34
  */
32
- type JWKLookupFunction = (header: JWKLookupFunctionHeader, token: string) => CryptoKey | JWK | JWKSet | string | Uint8Array<ArrayBuffer> | Promise<CryptoKey | JWK | JWKSet | string | Uint8Array<ArrayBuffer>>;
35
+ type JWKLookupFunction<TReturn = CryptoKey | JWK | JWKSet | string | Uint8Array<ArrayBuffer>> = (header: JWKLookupFunctionHeader, token: string) => TReturn | Promise<TReturn>;
33
36
  /**
34
37
  * Interface for custom JWK import cache implementations.
35
38
  *
@@ -78,16 +81,7 @@ interface GenerateKeyOptions {
78
81
  */
79
82
  toJWK?: boolean;
80
83
  }
81
- type GenerateKeyReturnJWK<TAlg extends GenerateKeyAlgorithm> = TAlg extends JWK_Asymmetric_Algorithm ? TAlg extends JWK_RSA_SIGN | JWK_RSA_PSS | JWK_RSA_ENC ? {
82
- privateKey: JWK_RSA_Private;
83
- publicKey: JWK_RSA_Public;
84
- } : TAlg extends JWK_ECDSA | JWK_ECDH_ES ? {
85
- privateKey: JWK_EC_Private;
86
- publicKey: JWK_EC_Public;
87
- } : TAlg extends JWK_OKP_SIGN ? {
88
- privateKey: JWK_OKP_Private;
89
- publicKey: JWK_OKP_Public;
90
- } : never : TAlg extends JWK_AES_CBC_HMAC | JWK_Symmetric_Algorithm ? JWK_oct : never;
84
+ type GenerateKeyReturnJWK<TAlg extends GenerateKeyAlgorithm> = TAlg extends JWK_Asymmetric_Algorithm ? JWK_Pair<TAlg> : TAlg extends JWK_AES_CBC_HMAC | JWK_Symmetric_Algorithm ? JWK_oct<TAlg> : never;
91
85
  type GenerateKeyReturnCrypto<TAlg extends GenerateKeyAlgorithm> = TAlg extends JWK_AES_CBC_HMAC ? Uint8Array<ArrayBuffer> : TAlg extends JWK_Asymmetric_Algorithm ? CryptoKeyPair : CryptoKey;
92
86
  type GenerateKeyReturn<TAlg extends GenerateKeyAlgorithm, TOptions extends GenerateKeyOptions> = TOptions["toJWK"] extends true ? GenerateKeyReturnJWK<TAlg> : GenerateKeyReturnCrypto<TAlg>;
93
87
  type GenerateJWKOptions = Omit<GenerateKeyOptions, "toJWK">;
@@ -109,9 +103,27 @@ interface DeriveKeyOptions {
109
103
  */
110
104
  toJWK?: boolean;
111
105
  }
112
- type DeriveKeyReturn<TOptions extends DeriveKeyOptions> = TOptions["toJWK"] extends true ? JWK_oct : TOptions["toJWK"] extends object ? JWK_oct : CryptoKey;
106
+ /** PBES2 → AES-KW alg that ends up stamped on the derived JWK's `alg`. */
107
+ type DerivedJWKAlg<TAlg extends JWK_PBES2> = TAlg extends "PBES2-HS256+A128KW" ? "A128KW" : TAlg extends "PBES2-HS384+A192KW" ? "A192KW" : TAlg extends "PBES2-HS512+A256KW" ? "A256KW" : JWK_AES_KW;
108
+ type DeriveKeyReturn<TOptions extends DeriveKeyOptions, TAlg extends JWK_PBES2 = JWK_PBES2> = TOptions["toJWK"] extends true ? JWK_oct<DerivedJWKAlg<TAlg>> : TOptions["toJWK"] extends object ? JWK_oct<DerivedJWKAlg<TAlg>> : CryptoKey;
113
109
  type KeyManagementAlgorithm = JWK_RSA_ENC | JWK_AES_KW | JWK_AES_GCM | JWK_AES_GCM_KW | JWK_PBES2 | JWK_ECDH_ES | "dir";
114
110
  type ContentEncryptionAlgorithm = JWK_AES_GCM | JWK_AES_CBC_HMAC;
111
+ /**
112
+ * Keys admissible as the `wrappingKey` argument of {@link wrapKey}, narrowed
113
+ * by the key management algorithm. Mirrors the runtime branches in
114
+ * `jwk.wrapKey` and the inference in `inferJWEAllowedAlgorithms`.
115
+ *
116
+ * - `dir` accepts any symmetric JWK (the key _is_ the CEK).
117
+ * - AES-GCMKW tolerates a JWK whose `alg` is the bare `A*GCM` counterpart —
118
+ * matches the `jweAlgsFromOctJWK` aliasing rule.
119
+ */
120
+ type WrappingKeyFor<A extends KeyManagementAlgorithm> = A extends JWK_RSA_ENC ? CryptoKey | JWK_RSA_Public<A> : A extends JWK_ECDH_ES ? CryptoKey | JWK_EC_Public<A> | JWK_OKP_Public<A> : A extends JWK_PBES2 ? string | Uint8Array<ArrayBuffer> | JWK_oct<A> : A extends JWK_AES_KW ? CryptoKey | JWK_oct<A> : A extends JWK_AES_GCM_KW ? CryptoKey | JWK_oct<A | `A${"128" | "192" | "256"}GCM`> : A extends "dir" ? CryptoKey | JWK_oct | Uint8Array<ArrayBuffer> : never;
121
+ /**
122
+ * Keys admissible as the `unwrappingKey` argument of {@link unwrapKey}.
123
+ * The private-side counterpart of {@link WrappingKeyFor} — symmetric branches
124
+ * are identical; asymmetric branches use the `_Private` variants.
125
+ */
126
+ type UnwrappingKeyFor<A extends KeyManagementAlgorithm> = A extends JWK_RSA_ENC ? CryptoKey | JWK_RSA_Private<A> : A extends JWK_ECDH_ES ? CryptoKey | JWK_EC_Private<A> | JWK_OKP_Private<A> : A extends JWK_PBES2 ? string | Uint8Array<ArrayBuffer> | JWK_oct<A> : A extends JWK_AES_KW ? CryptoKey | JWK_oct<A> : A extends JWK_AES_GCM_KW ? CryptoKey | JWK_oct<A | `A${"128" | "192" | "256"}GCM`> : A extends "dir" ? CryptoKey | JWK_oct | Uint8Array<ArrayBuffer> : never;
115
127
  /** Options for the wrapKey function. */
116
128
  interface WrapKeyOptions {
117
129
  /** Initialization Vector for AES-GCMKW. Generated if not provided. */
@@ -140,25 +152,31 @@ interface WrapKeyOptions {
140
152
  enc?: ContentEncryptionAlgorithm;
141
153
  };
142
154
  }
143
- /** Result of the wrapKey function. */
144
- interface WrapKeyResult {
145
- /** The wrapped key (Ciphertext). */
146
- encryptedKey: Uint8Array<ArrayBuffer>;
147
- /** Initialization Vector used (only for AES-GCMKW). Base64URL encoded. */
148
- iv?: string;
149
- /** Authentication Tag generated (only for AES-GCMKW). Base64URL encoded. */
150
- tag?: string;
151
- /** PBES2 Salt value used (only for PBES2). Base64URL encoded. */
152
- p2s?: string;
153
- /** PBES2 Iteration count used (only for PBES2). */
154
- p2c?: number;
155
- /** ECDH-ES Ephemeral Public Key used (only for ECDH-ES). */
156
- epk?: JWK_EC_Public;
157
- /** ECDH-ES Agreement PartyUInfo used (only for ECDH-ES). Base64URL encoded. */
158
- apu?: string;
159
- /** ECDH-ES Agreement PartyVInfo used (only for ECDH-ES). Base64URL encoded. */
155
+ /**
156
+ * Result of {@link wrapKey}, discriminated by key management algorithm family.
157
+ *
158
+ * Narrow the shape by passing a literal `alg` to `wrapKey`:
159
+ * - PBES2 → `{ encryptedKey, p2s, p2c }`
160
+ * - AES-GCMKW → `{ encryptedKey, iv, tag }`
161
+ * - ECDH-ES / ECDH-ES+A*KW → `{ encryptedKey, epk, apu?, apv? }`
162
+ * - dir / AES-KW / RSA-OAEP → `{ encryptedKey }`
163
+ */
164
+ type WrapKeyResult<TAlg extends KeyManagementAlgorithm = KeyManagementAlgorithm> = TAlg extends JWK_PBES2 ? {
165
+ encryptedKey: Uint8Array<ArrayBuffer>; /** PBES2 Salt value (p2s). Base64URL encoded. */
166
+ p2s: string; /** PBES2 Iteration count (p2c). */
167
+ p2c: number;
168
+ } : TAlg extends JWK_AES_GCM_KW ? {
169
+ encryptedKey: Uint8Array<ArrayBuffer>; /** AES-GCMKW Initialization Vector. Base64URL encoded. */
170
+ iv: string; /** AES-GCMKW Authentication Tag. Base64URL encoded. */
171
+ tag: string;
172
+ } : TAlg extends JWK_ECDH_ES ? {
173
+ encryptedKey: Uint8Array<ArrayBuffer>; /** Ephemeral Public Key. */
174
+ epk: JWK_EC_Public; /** Agreement PartyUInfo. Base64URL encoded. Present only when supplied. */
175
+ apu?: string; /** Agreement PartyVInfo. Base64URL encoded. Present only when supplied. */
160
176
  apv?: string;
161
- }
177
+ } : {
178
+ encryptedKey: Uint8Array<ArrayBuffer>;
179
+ };
162
180
  /** Options for the unwrapKey function. */
163
181
  interface UnwrapKeyOptions {
164
182
  /**
@@ -176,6 +194,10 @@ interface UnwrapKeyOptions {
176
194
  p2s?: Uint8Array<ArrayBuffer> | string;
177
195
  /** PBES2 Iteration count (required for PBES2). */
178
196
  p2c?: number;
197
+ /** Minimum accepted PBES2 `p2c` on unwrap. Defaults to 1000 (RFC 7518 §4.8.1.2). */
198
+ minIterations?: number;
199
+ /** Maximum accepted PBES2 `p2c` on unwrap. Defaults to 1_000_000 to cap PBKDF2 DoS potential. */
200
+ maxIterations?: number;
179
201
  /** ECDH-ES Ephemeral Public Key (required for ECDH-ES). */
180
202
  epk?: JWK_EC_Public | CryptoKey;
181
203
  /** ECDH-ES Agreement PartyUInfo. Base64URL encoded or Uint8Array. */
@@ -196,8 +218,15 @@ interface UnwrapKeyOptions {
196
218
  * Copyright (c) 2018 Filip Skokan.
197
219
  * LICENSE: https://github.com/panva/jose/blob/v6.0.10/LICENSE.md
198
220
  */
199
- /** Generic JSON Web Key Parameters. */
200
- interface JWKParameters {
221
+ /**
222
+ * Generic JSON Web Key Parameters.
223
+ *
224
+ * The `Alg` type parameter constrains the JWK's `alg` field. Each concrete JWK
225
+ * interface below tightens `Alg` to the algorithm family admissible for that key
226
+ * type — e.g. a `JWK_oct<JWK_HMAC>` can only hold `"HS256" | "HS384" | "HS512"`
227
+ * in `alg`.
228
+ */
229
+ interface JWKParameters<Alg extends string = string> {
201
230
  /** JWK "kty" (Key Type) Parameter */
202
231
  kty: string;
203
232
  /**
@@ -205,7 +234,7 @@ interface JWKParameters {
205
234
  *
206
235
  * @see {@link https://github.com/panva/jose/issues/210 Algorithm Key Requirements}
207
236
  */
208
- alg?: string;
237
+ alg?: Alg;
209
238
  /** JWK "key_ops" (Key Operations) Parameter */
210
239
  key_ops?: KeyUsage[];
211
240
  /** JWK "ext" (Extractable) Parameter */
@@ -230,7 +259,7 @@ interface JWKParameters {
230
259
  enc?: ContentEncryptionAlgorithm;
231
260
  }
232
261
  /** Public EC JSON Web Keys */
233
- interface JWK_EC_Public extends JWKParameters {
262
+ interface JWK_EC_Public<Alg extends JWK_ECDSA | JWK_ECDH_ES | (string & {}) = string> extends JWKParameters<Alg> {
234
263
  /** EC JWK "kty" (Key Type) Parameter */
235
264
  kty: "EC";
236
265
  /** EC JWK "crv" (Curve) Parameter */
@@ -241,14 +270,14 @@ interface JWK_EC_Public extends JWKParameters {
241
270
  y: string;
242
271
  }
243
272
  /** Private EC JSON Web Keys */
244
- interface JWK_EC_Private extends JWK_EC_Public {
273
+ interface JWK_EC_Private<Alg extends JWK_ECDSA | JWK_ECDH_ES | (string & {}) = string> extends JWK_EC_Public<Alg> {
245
274
  /** EC JWK "d" (ECC Private Key) Parameter */
246
275
  d: string;
247
276
  }
248
277
  /** EC JSON Web Keys */
249
- type JWK_EC = JWK_EC_Public | JWK_EC_Private;
278
+ type JWK_EC<Alg extends JWK_ECDSA | JWK_ECDH_ES | (string & {}) = string> = JWK_EC_Public<Alg> | JWK_EC_Private<Alg>;
250
279
  /** Public RSA JSON Web Keys */
251
- interface JWK_RSA_Public extends JWKParameters {
280
+ interface JWK_RSA_Public<Alg extends JWK_RSA_SIGN | JWK_RSA_PSS | JWK_RSA_ENC | (string & {}) = string> extends JWKParameters<Alg> {
252
281
  /** RSA JWK "kty" (Key Type) Parameter */
253
282
  kty: "RSA";
254
283
  /** RSA JWK "e" (Exponent) Parameter */
@@ -258,7 +287,7 @@ interface JWK_RSA_Public extends JWKParameters {
258
287
  oth?: RsaOtherPrimesInfo[];
259
288
  }
260
289
  /** Private RSA JSON Web Keys */
261
- interface JWK_RSA_Private extends JWK_RSA_Public {
290
+ interface JWK_RSA_Private<Alg extends JWK_RSA_SIGN | JWK_RSA_PSS | JWK_RSA_ENC | (string & {}) = string> extends JWK_RSA_Public<Alg> {
262
291
  /** RSA JWK "d" (Private Exponent) Parameter */
263
292
  d: string;
264
293
  /** RSA JWK "dp" (First Factor CRT Exponent) Parameter */
@@ -273,9 +302,9 @@ interface JWK_RSA_Private extends JWK_RSA_Public {
273
302
  qi: string;
274
303
  }
275
304
  /** RSA JSON Web Keys */
276
- type JWK_RSA = JWK_RSA_Public | JWK_RSA_Private;
305
+ type JWK_RSA<Alg extends JWK_RSA_SIGN | JWK_RSA_PSS | JWK_RSA_ENC | (string & {}) = string> = JWK_RSA_Public<Alg> | JWK_RSA_Private<Alg>;
277
306
  /** Public ED JSON Web Keys */
278
- interface JWK_OKP_Public extends JWKParameters {
307
+ interface JWK_OKP_Public<Alg extends JWK_OKP_SIGN | JWK_ECDH_ES | (string & {}) = string> extends JWKParameters<Alg> {
279
308
  /** ED JWK "kty" (Key Type) Parameter */
280
309
  kty: "OKP";
281
310
  /** ED JWK "crv" (Curve) Parameter */
@@ -284,48 +313,78 @@ interface JWK_OKP_Public extends JWKParameters {
284
313
  x: string;
285
314
  }
286
315
  /** Private ED JSON Web Keys */
287
- interface JWK_OKP_Private extends JWK_OKP_Public {
316
+ interface JWK_OKP_Private<Alg extends JWK_OKP_SIGN | JWK_ECDH_ES | (string & {}) = string> extends JWK_OKP_Public<Alg> {
288
317
  /** ED JWK "d" (Private Key) Parameter */
289
318
  d: string;
290
319
  }
291
320
  /** OKP JSON Web Keys */
292
- type JWK_OKP = JWK_OKP_Public | JWK_OKP_Private;
321
+ type JWK_OKP<Alg extends JWK_OKP_SIGN | JWK_ECDH_ES | (string & {}) = string> = JWK_OKP_Public<Alg> | JWK_OKP_Private<Alg>;
293
322
  /** oct JSON Web Keys */
294
- interface JWK_oct extends JWKParameters {
323
+ interface JWK_oct<Alg extends JWK_HMAC | JWK_AES_KW | JWK_AES_GCM | JWK_AES_GCM_KW | JWK_AES_CBC_HMAC | JWK_PBES2 | "dir" | (string & {}) = string> extends JWKParameters<Alg> {
295
324
  /** Oct JWK "k" (Key Value) Parameter */
296
325
  k: string;
297
326
  }
298
327
  /** Symmetric JSON Web Keys */
299
- type JWK_Symmetric = JWK_oct;
328
+ type JWK_Symmetric<Alg extends JWK_HMAC | JWK_AES_KW | JWK_AES_GCM | JWK_AES_GCM_KW | JWK_AES_CBC_HMAC | JWK_PBES2 | "dir" | (string & {}) = string> = JWK_oct<Alg>;
300
329
  /** Asymmetric JSON Web Keys */
301
- type JWK_Asymmetric = JWK_RSA | JWK_EC | JWK_OKP;
330
+ type JWK_Asymmetric<Alg extends string = string> = JWK_RSA<Alg> | JWK_EC<Alg> | JWK_OKP<Alg>;
302
331
  /** Public JSON Web Keys */
303
- type JWK_Public = JWK_RSA_Public | JWK_EC_Public | JWK_OKP_Public;
332
+ type JWK_Public<Alg extends string = string> = JWK_RSA_Public<Alg> | JWK_EC_Public<Alg> | JWK_OKP_Public<Alg>;
304
333
  /** Private JSON Web Keys */
305
- type JWK_Private = JWK_RSA_Private | JWK_EC_Private | JWK_OKP_Private;
334
+ type JWK_Private<Alg extends string = string> = JWK_RSA_Private<Alg> | JWK_EC_Private<Alg> | JWK_OKP_Private<Alg>;
306
335
  /**
307
336
  * JSON Web Key ({@link https://www.rfc-editor.org/rfc/rfc7517 JWK}). "RSA", "EC", "OKP" and "oct" key types are supported.
308
337
  */
309
- type JWK = JWK_oct | JWK_RSA | JWK_EC | JWK_OKP;
338
+ type JWK<Alg extends string = string> = JWK_oct<Alg> | JWK_RSA<Alg> | JWK_EC<Alg> | JWK_OKP<Alg>;
310
339
  /**
311
- * A pair of public and private JSON Web Keys.
340
+ * A pair of public and private JSON Web Keys, narrowed by `Alg` when that
341
+ * uniquely identifies the key family:
342
+ *
343
+ * - `JWK_Pair<"RS256">` → RSA pair only
344
+ * - `JWK_Pair<"ES256">` → EC pair only
345
+ * - `JWK_Pair<"ECDH-ES+A256KW">` → EC pair **or** OKP pair (curve decides at runtime)
346
+ * - `JWK_Pair<"Ed25519">` / `JWK_Pair<"EdDSA">` → OKP pair only
347
+ *
348
+ * The final branch is a generic fallback (`Alg = string`, or any custom /
349
+ * forward-compat algorithm that doesn't match a known family) — it yields
350
+ * the permissive three-branch union.
312
351
  */
313
- type JWK_Pair = {
314
- publicKey: JWK_RSA_Public;
315
- privateKey: JWK_RSA_Private;
352
+ type JWK_Pair<Alg extends string = string> = Alg extends JWK_RSA_SIGN | JWK_RSA_PSS | JWK_RSA_ENC ? {
353
+ publicKey: JWK_RSA_Public<Alg>;
354
+ privateKey: JWK_RSA_Private<Alg>;
355
+ } : Alg extends JWK_ECDSA ? {
356
+ publicKey: JWK_EC_Public<Alg>;
357
+ privateKey: JWK_EC_Private<Alg>;
358
+ } : Alg extends JWK_ECDH_ES ? {
359
+ publicKey: JWK_EC_Public<Alg>;
360
+ privateKey: JWK_EC_Private<Alg>;
316
361
  } | {
317
- publicKey: JWK_EC_Public;
318
- privateKey: JWK_EC_Private;
362
+ publicKey: JWK_OKP_Public<Alg>;
363
+ privateKey: JWK_OKP_Private<Alg>;
364
+ } : Alg extends JWK_OKP_SIGN ? {
365
+ publicKey: JWK_OKP_Public<Alg>;
366
+ privateKey: JWK_OKP_Private<Alg>;
367
+ } : {
368
+ publicKey: JWK_RSA_Public<Alg>;
369
+ privateKey: JWK_RSA_Private<Alg>;
319
370
  } | {
320
- publicKey: JWK_OKP_Public;
321
- privateKey: JWK_OKP_Private;
371
+ publicKey: JWK_EC_Public<Alg>;
372
+ privateKey: JWK_EC_Private<Alg>;
373
+ } | {
374
+ publicKey: JWK_OKP_Public<Alg>;
375
+ privateKey: JWK_OKP_Private<Alg>;
322
376
  };
323
377
  /**
324
378
  * JSON Web Key Set ({@link https://www.rfc-editor.org/rfc/rfc7517 JWK Set}). "RSA", "EC" and "oct" key types are supported.
379
+ *
380
+ * The optional `T` generic preserves the precise key tuple when constructed
381
+ * in TS — e.g. `JWKSet<[JWK_oct<"HS256">, JWK_EC_Public<"ES256">]>` — while the
382
+ * default `JWK[]` keeps the permissive behavior expected for JWKS fetched from
383
+ * external sources (runtime trials each candidate).
325
384
  */
326
- interface JWKSet {
385
+ interface JWKSet<T extends readonly JWK[] = JWK[]> {
327
386
  /** JWK Set "keys" Parameter */
328
- keys: JWK[];
387
+ keys: T;
329
388
  [parameter: string]: unknown;
330
389
  }
331
390
  /** JWK Key Algorithms */
@@ -345,8 +404,6 @@ type JWK_Symmetric_Algorithm = JWK_HMAC | JWK_AES_KW | JWK_AES_GCM | JWK_AES_GCM
345
404
  type JWK_Asymmetric_Algorithm = JWK_RSA_SIGN | JWK_RSA_PSS | JWK_ECDSA | JWK_RSA_ENC | JWK_OKP_SIGN | JWK_ECDH_ES;
346
405
  type JWKAlgorithm = JWK_Symmetric_Algorithm | JWK_Asymmetric_Algorithm | JWK_AES_CBC_HMAC | JWK_PBES2 | JWK_ECDH_ES | "dir";
347
406
  type JWKPEMAlgorithm = JWK_RSA_PSS | JWK_RSA_SIGN | JWK_RSA_ENC | JWK_ECDSA | JWK_ECDH_ES | JWK_OKP_SIGN;
348
- //#endregion
349
- //#region src/core/types/jwt.d.ts
350
407
  /** Header Parameters common to JWE and JWS */
351
408
  interface JoseHeaderParameters {
352
409
  /** "kid" (Key ID) Header Parameter */
@@ -412,7 +469,11 @@ interface JWTClaimValidationOptions {
412
469
  subject?: string;
413
470
  /** Maximum token age, from the JWT "iat" (Issued At) Claim value. Implies presence requirement. */
414
471
  maxTokenAge?: MaxTokenAge;
415
- /** Clock skew tolerance (in seconds) for validating time-based claims (nbf/exp/iat). */
472
+ /**
473
+ * Clock skew tolerance (in seconds) for validating time-based claims (nbf/exp/iat).
474
+ *
475
+ * @default 0
476
+ */
416
477
  clockTolerance?: number;
417
478
  /** Expected JWT "typ" (Type) Header Parameter value. Implies presence requirement. */
418
479
  typ?: string;
@@ -428,10 +489,99 @@ interface JWTClaimValidationOptions {
428
489
  */
429
490
  recognizedHeaders?: string[];
430
491
  }
431
- //#endregion
432
- //#region src/core/types/jws.d.ts
492
+ /**
493
+ * All known error codes thrown by unjwt.
494
+ *
495
+ * Code naming follows the JOSE spec hierarchy:
496
+ * ERR_JWT_* — RFC 7519 JSON Web Token claim validation
497
+ * ERR_JWS_* — RFC 7515 JSON Web Signature
498
+ * ERR_JWE_* — RFC 7516 JSON Web Encryption
499
+ * ERR_JWK_* — RFC 7517 JSON Web Key
500
+ */
501
+ type JWTErrorCode = "ERR_JWT_EXPIRED" | "ERR_JWT_NBF" | "ERR_JWT_CLAIM_INVALID" | "ERR_JWT_CLAIM_MISSING" | "ERR_JWS_INVALID" | "ERR_JWS_INVALID_SERIALIZATION" | "ERR_JWS_SIGNATURE_INVALID" | "ERR_JWS_ALG_NOT_ALLOWED" | "ERR_JWS_ALG_MISSING" | "ERR_JWS_SIGNER_ALG_INFERENCE" | "ERR_JWS_NO_MATCHING_SIGNER" | "ERR_JWS_HEADER_PARAMS_NOT_DISJOINT" | "ERR_JWS_B64_INCONSISTENT" | "ERR_JWE_INVALID" | "ERR_JWE_INVALID_SERIALIZATION" | "ERR_JWE_DECRYPTION_FAILED" | "ERR_JWE_ALG_NOT_ALLOWED" | "ERR_JWE_ALG_MISSING" | "ERR_JWE_ALG_FORBIDDEN_IN_MULTI" | "ERR_JWE_ENC_MISSING" | "ERR_JWE_RECIPIENT_ALG_INFERENCE" | "ERR_JWE_NO_MATCHING_RECIPIENT" | "ERR_JWE_HEADER_PARAMS_NOT_DISJOINT" | "ERR_JWK_INVALID" | "ERR_JWK_KEY_NOT_FOUND" | "ERR_JWK_UNSUPPORTED" | (string & {});
502
+ /**
503
+ * Maps known error codes to their structured `cause` shapes.
504
+ * Only codes that carry decoded context beyond the message appear here.
505
+ * Extend this interface when new structured causes are introduced.
506
+ */
507
+ interface JWTErrorCauseMap {
508
+ /** Decoded claims available at the point the lifetime check failed. */
509
+ ERR_JWT_EXPIRED: {
510
+ jti?: string;
511
+ iat?: number;
512
+ exp?: number;
513
+ };
514
+ }
515
+ /**
516
+ * Base error class for all unjwt errors. Every error thrown by the library is
517
+ * an instance of `JWTError`, so a single `instanceof` check is sufficient to
518
+ * distinguish library errors from other thrown values. Use the `code` property
519
+ * (or the `isJWTError` type guard) to narrow to a specific error condition.
520
+ *
521
+ * @example
522
+ * import { JWTError, isJWTError } from "unjwt/jws";
523
+ *
524
+ * try {
525
+ * await verify(token, key);
526
+ * } catch (err) {
527
+ * if (isJWTError(err, "ERR_JWT_EXPIRED")) {
528
+ * console.log(err.cause.jti); // string | undefined
529
+ * }
530
+ * }
531
+ */
532
+ declare class JWTError<TCode extends JWTErrorCode = JWTErrorCode> extends Error {
533
+ readonly code: TCode;
534
+ override readonly cause?: unknown;
535
+ constructor(message: string, code: TCode, cause?: unknown);
536
+ }
537
+ /**
538
+ * Type guard that narrows `error` to `JWTError`.
539
+ *
540
+ * When called with a code that is a key of `JWTErrorCauseMap`, the return
541
+ * type is additionally narrowed to include the structured `cause` shape for
542
+ * that code. When called with any other `JWTErrorCode`, `code` is narrowed
543
+ * but `cause` remains `unknown`. When called without a code, narrows only to
544
+ * `JWTError`.
545
+ *
546
+ * @example
547
+ * if (isJWTError(err, "ERR_JWT_EXPIRED")) {
548
+ * err.cause.jti // string | undefined ✓
549
+ * }
550
+ */
551
+ declare function isJWTError<T extends keyof JWTErrorCauseMap>(error: unknown, code: T): error is JWTError<T> & {
552
+ cause: JWTErrorCauseMap[T];
553
+ };
554
+ declare function isJWTError<T extends JWTErrorCode>(error: unknown, code: T): error is JWTError<T>;
555
+ declare function isJWTError(error: unknown): error is JWTError;
556
+ type StrictOmit<T, K extends keyof T | (string & {}) | (number & {}) | (symbol & {})> = { [P in keyof T as P extends K ? never : P]: T[P] };
433
557
  /** JWS Signing Algorithm Identifier. */
434
558
  type JWSAlgorithm = JWK_HMAC | JWK_RSA_SIGN | JWK_RSA_PSS | JWK_ECDSA | JWK_OKP_SIGN;
559
+ /**
560
+ * Asymmetric private JWKs admissible as a signing key. RSA keys carry a
561
+ * signing `alg` (RS* or PS*); EC keys carry an ECDSA alg; OKP keys carry an Ed
562
+ * signing alg.
563
+ */
564
+ type JWSAsymmetricPrivateJWK = JWK_RSA_Private<JWK_RSA_SIGN | JWK_RSA_PSS> | JWK_EC_Private<JWK_ECDSA> | JWK_OKP_Private<JWK_OKP_SIGN>;
565
+ /**
566
+ * Asymmetric public JWKs admissible as a verification key. RSA keys carry a
567
+ * signing `alg` (RS* or PS*); EC keys carry an ECDSA alg; OKP keys carry an Ed
568
+ * signing alg.
569
+ */
570
+ type JWSAsymmetricPublicJWK = JWK_RSA_Public<JWK_RSA_SIGN | JWK_RSA_PSS> | JWK_EC_Public<JWK_ECDSA> | JWK_OKP_Public<JWK_OKP_SIGN>;
571
+ /**
572
+ * JWKs admissible as the `key` argument of {@link sign}. HMAC oct keys carry a
573
+ * {@link JWK_HMAC} alg; asymmetric private keys carry their family's signing alg.
574
+ * A JWK whose `alg` points at a non-signing family (e.g. `"RSA-OAEP"`) is
575
+ * rejected at the type level.
576
+ */
577
+ type JWSSignJWK = JWK_oct<JWK_HMAC> | JWSAsymmetricPrivateJWK;
578
+ /**
579
+ * JWKs admissible as a `key` for {@link verify}. HMAC oct keys carry a
580
+ * {@link JWK_HMAC} alg; asymmetric public keys carry their family's signing alg.
581
+ * A JWK whose `alg` points at a non-signing family (e.g. `"RSA-OAEP"`) is
582
+ * rejected at the type level.
583
+ */
584
+ type JWSVerifyJWK = JWK_oct<JWK_HMAC> | JWSAsymmetricPublicJWK;
435
585
  /** Recognized JWS Header Parameters, any other Header Members may also be present. */
436
586
  interface JWSHeaderParameters extends JoseHeaderParameters {
437
587
  /** JWS "alg" (Algorithm) Header Parameter */
@@ -455,16 +605,45 @@ interface JWSSignOptions {
455
605
  /** The JWS Algorithm to use. Must be provided. */
456
606
  alg?: JWSAlgorithm;
457
607
  /**
458
- * Additional protected header parameters. `alg` is automatically included.
459
- * `typ` defaults to "JWT" if not provided and payload is an object.
608
+ * Additional protected header parameters. `alg` is always derived from the top-level `alg`
609
+ * option (or inferred from the key) and cannot be overridden. `typ` defaults to `"JWT"`
610
+ * when the payload is a JSON object.
460
611
  */
461
- protectedHeader?: JWSHeaderParameters;
612
+ protectedHeader?: StrictOmit<JWSHeaderParameters, "alg"> & {
613
+ alg?: never;
614
+ };
462
615
  /** Date to use when comparing NumericDate claims, defaults to `new Date()`. */
463
616
  currentDate?: Date;
464
617
  /**
465
- * Time at which the JWS should expire, if no `exp` was already provided.
618
+ * Duration until the JWS should expire, relative to `currentDate` (or `new Date()`).
619
+ * Skipped when the payload already carries an `exp` claim.
620
+ *
621
+ * Mutually exclusive with {@link expiresAt}.
466
622
  */
467
623
  expiresIn?: ExpiresIn;
624
+ /**
625
+ * Absolute moment at which the JWS should expire (sets the `exp` claim directly).
626
+ * Skipped when the payload already carries an `exp` claim.
627
+ *
628
+ * Mutually exclusive with {@link expiresIn}.
629
+ */
630
+ expiresAt?: Date;
631
+ /**
632
+ * Duration from `iat` before which the JWS must not be accepted.
633
+ * `0` is allowed and sets `nbf = iat` (explicit temporal floor at sign time).
634
+ * Skipped when the payload already carries an `nbf` claim.
635
+ *
636
+ * Mutually exclusive with {@link notBeforeAt}.
637
+ */
638
+ notBeforeIn?: ExpiresIn;
639
+ /**
640
+ * Absolute moment before which the JWS must not be accepted (sets the `nbf`
641
+ * claim directly per RFC 7519 §4.1.5). Skipped when the payload already
642
+ * carries an `nbf` claim.
643
+ *
644
+ * Mutually exclusive with {@link notBeforeIn}.
645
+ */
646
+ notBeforeAt?: Date;
468
647
  }
469
648
  /** Result of JWS verification */
470
649
  interface JWSVerifyResult<T extends JOSEPayload = JOSEPayload> {
@@ -488,11 +667,146 @@ interface JWSVerifyOptions extends JWTClaimValidationOptions {
488
667
  */
489
668
  validateClaims?: boolean;
490
669
  }
491
- //#endregion
492
- //#region src/core/utils/types.d.ts
493
- type StrictOmit<T, K extends keyof T | (string & {}) | (number & {}) | (symbol & {})> = { [P in keyof T as P extends K ? never : P]: T[P] };
494
- //#endregion
495
- //#region src/core/types/jwe.d.ts
670
+ /**
671
+ * JWS Flattened JSON Serialization, RFC 7515 §7.2.2. Accepted as input by
672
+ * {@link verifyMulti} and normalized to {@link JWSGeneralSerialization}
673
+ * internally. Emitted by {@link generalToFlattenedJWS} on a single-signature
674
+ * General serialization.
675
+ */
676
+ interface JWSFlattenedSerialization {
677
+ /** The JWS Payload. base64url-encoded when `b64 !== false`. */
678
+ payload: string;
679
+ /** Base64URL-encoded JWS Protected Header (part of the signing input). */
680
+ protected?: string;
681
+ /** JWS Unprotected Header (not part of the signing input). */
682
+ header?: JWSHeaderParameters;
683
+ /** Base64URL-encoded signature bytes. */
684
+ signature: string;
685
+ }
686
+ /**
687
+ * JWS General JSON Serialization, RFC 7515 §7.2.1. Canonical multi-signature
688
+ * output shape of {@link signMulti}.
689
+ *
690
+ * `payload` is shared across all signatures and carries base64url-encoded
691
+ * bytes by default. When the consistent `b64: false` signing mode is used
692
+ * (RFC 7797), `payload` holds the raw UTF-8 payload string instead.
693
+ */
694
+ interface JWSGeneralSerialization extends Omit<JWSFlattenedSerialization, "protected" | "header" | "signature"> {
695
+ /** One entry per signer. */
696
+ signatures: JWSGeneralSignature[];
697
+ }
698
+ /** A single signature entry within {@link JWSGeneralSerialization.signatures}. */
699
+ type JWSGeneralSignature = Pick<JWSFlattenedSerialization, "protected" | "header" | "signature">;
700
+ /**
701
+ * Input shape for a single signer passed to {@link signMulti}.
702
+ *
703
+ * `alg` is inferred from `key.alg`; throws `ERR_JWS_SIGNER_ALG_INFERENCE`
704
+ * when absent. `kid` is pulled from `key.kid` when present.
705
+ */
706
+ interface JWSMultiSigner {
707
+ /** Signing key (JWK-first; `alg` inferred from `key.alg`). */
708
+ key: JWSSignJWK;
709
+ /**
710
+ * Extra per-signer JWS Protected Header parameters (RFC 7515 §7.2.1).
711
+ * `alg` is always derived from the JWK and cannot be set here. `b64`
712
+ * MUST be consistent across every signer (RFC 7797 §3) — if set on one
713
+ * signer it must match on all.
714
+ */
715
+ protectedHeader?: StrictOmit<JWSHeaderParameters, "alg"> & {
716
+ alg?: never;
717
+ };
718
+ /** Per-signer JWS Unprotected Header (not part of signing input). */
719
+ unprotectedHeader?: JWSHeaderParameters;
720
+ }
721
+ /**
722
+ * Options for {@link signMulti}. Mirrors {@link JWSSignOptions} minus the
723
+ * per-signer fields (`alg`, `protectedHeader` — set those on each
724
+ * {@link JWSMultiSigner} instead).
725
+ */
726
+ interface JWSMultiSignOptions extends StrictOmit<JWSSignOptions, "alg" | "protectedHeader"> {}
727
+ /** Options for {@link verifyMulti}. Extends {@link JWSVerifyOptions}. */
728
+ interface JWSMultiVerifyOptions extends JWSVerifyOptions {
729
+ /**
730
+ * When `false` (default), verification trials signatures in order — mirrors
731
+ * the multi-key retry behaviour of {@link verify} against a JWK Set. When
732
+ * `true`, only signatures whose header unambiguously matches the provided
733
+ * key (by `kid`, then by `kty`/`crv`/length) are attempted, and any
734
+ * mismatch throws `ERR_JWS_NO_MATCHING_SIGNER` before any crypto work.
735
+ */
736
+ strictSignerMatch?: boolean;
737
+ }
738
+ /**
739
+ * Result of a {@link verifyMulti} operation. Extends {@link JWSVerifyResult}
740
+ * with the per-signer header and matched signature index.
741
+ */
742
+ interface JWSMultiVerifyResult<T extends JOSEPayload = JOSEPayload> extends JWSVerifyResult<T> {
743
+ /** Parsed per-signer unprotected header of the signature that verified. */
744
+ signerHeader?: JWSHeaderParameters;
745
+ /** Index into `jws.signatures` of the signature that successfully verified. */
746
+ signerIndex: number;
747
+ }
748
+ /**
749
+ * Options for {@link verifyMultiAll}. Inherits the same validation knobs as
750
+ * {@link JWSMultiVerifyOptions} minus `strictSignerMatch` (not meaningful when
751
+ * every signature is independently reported).
752
+ */
753
+ interface JWSMultiVerifyAllOptions extends StrictOmit<JWSMultiVerifyOptions, "strictSignerMatch"> {}
754
+ /**
755
+ * Per-signature outcome collected by {@link verifyMultiAll}. Discriminated by
756
+ * `verified`:
757
+ *
758
+ * - `verified: true` — the signature cryptographically verified and any
759
+ * claim/`crit` validation the caller asked for also passed. `payload` is
760
+ * provided.
761
+ * - `verified: false` — verification could not be completed for this
762
+ * signature. `error` carries the {@link JWTError} reason (signature
763
+ * invalid, disallowed alg, `typ` mismatch, key-resolver failure, malformed
764
+ * protected header, expired claim, etc.). `protectedHeader` / `signerHeader`
765
+ * are populated when they were successfully parsed before failure.
766
+ *
767
+ * Callers apply their own policy over the returned array — e.g. "all must
768
+ * verify", "quorum of N", "signed by these specific kids".
769
+ */
770
+ type JWSMultiVerifyOutcome<T extends JOSEPayload = JOSEPayload> = {
771
+ signerIndex: number;
772
+ verified: true;
773
+ payload: T;
774
+ protectedHeader: JWSProtectedHeader;
775
+ signerHeader?: JWSHeaderParameters;
776
+ } | {
777
+ signerIndex: number;
778
+ verified: false;
779
+ error: JWTError;
780
+ protectedHeader?: JWSProtectedHeader;
781
+ signerHeader?: JWSHeaderParameters;
782
+ };
783
+ /**
784
+ * Algorithms admissible on an `oct` JWK used for JWE key management. Mirrors
785
+ * the runtime aliasing table in `jweAlgsFromOctJWK` — HMAC algs intentionally
786
+ * excluded (they don't resolve to any JWE `alg`).
787
+ */
788
+ type _JWEOctAlg = JWK_AES_KW | JWK_AES_GCM | JWK_AES_GCM_KW | JWK_AES_CBC_HMAC | JWK_PBES2 | "dir";
789
+ /**
790
+ * Asymmetric public JWKs admissible for JWE encryption. RSA keys carry an
791
+ * RSA-OAEP alg; EC/OKP keys carry an ECDH-ES alg.
792
+ */
793
+ type JWEAsymmetricPublicJWK = JWK_RSA_Public<JWK_RSA_ENC> | JWK_EC_Public<JWK_ECDH_ES> | JWK_OKP_Public<JWK_ECDH_ES>;
794
+ /**
795
+ * Asymmetric private JWKs admissible for JWE decryption. RSA keys carry an
796
+ * RSA-OAEP alg; EC/OKP keys carry an ECDH-ES alg.
797
+ */
798
+ type JWEAsymmetricPrivateJWK = JWK_RSA_Private<JWK_RSA_ENC> | JWK_EC_Private<JWK_ECDH_ES> | JWK_OKP_Private<JWK_ECDH_ES>;
799
+ /**
800
+ * JWKs admissible as the `key` argument of {@link encrypt}. A JWK whose `alg`
801
+ * points at a non-JWE family (e.g. `"HS256"`, `"RS256"`) is rejected at the
802
+ * type level.
803
+ */
804
+ type JWEEncryptJWK = JWK_oct<_JWEOctAlg> | JWEAsymmetricPublicJWK;
805
+ /**
806
+ * JWKs admissible as a `key` for {@link decrypt}. A JWK whose `alg` points at
807
+ * a non-JWE family (e.g. `"HS256"`, `"RS256"`) is rejected at the type level.
808
+ */
809
+ type JWEDecryptJWK = JWK_oct<_JWEOctAlg> | JWEAsymmetricPrivateJWK;
496
810
  /** Recognized JWE Header Parameters, any other Header Members may also be present. */
497
811
  interface JWEHeaderParameters extends JoseHeaderParameters {
498
812
  /**
@@ -569,8 +883,36 @@ interface JWEEncryptOptions {
569
883
  enc?: ContentEncryptionAlgorithm;
570
884
  /** Date to use when computing NumericDate claims, defaults to `new Date()`. */
571
885
  currentDate?: Date;
572
- /** Time at which the JWT should expire, if no `exp` was already provided (only when typ is "JWT" or explicitly parsing JWT). */
886
+ /**
887
+ * Duration until the JWT should expire, relative to `currentDate` (or `new Date()`).
888
+ * Skipped when the payload already carries an `exp` claim.
889
+ *
890
+ * Mutually exclusive with {@link expiresAt}.
891
+ */
573
892
  expiresIn?: ExpiresIn;
893
+ /**
894
+ * Absolute moment at which the JWT should expire (sets the `exp` claim directly).
895
+ * Skipped when the payload already carries an `exp` claim.
896
+ *
897
+ * Mutually exclusive with {@link expiresIn}.
898
+ */
899
+ expiresAt?: Date;
900
+ /**
901
+ * Duration from `iat` before which the JWT must not be accepted.
902
+ * `0` is allowed and sets `nbf = iat` (explicit temporal floor at sign time).
903
+ * Skipped when the payload already carries an `nbf` claim.
904
+ *
905
+ * Mutually exclusive with {@link notBeforeAt}.
906
+ */
907
+ notBeforeIn?: ExpiresIn;
908
+ /**
909
+ * Absolute moment before which the JWT must not be accepted (sets the `nbf`
910
+ * claim directly per RFC 7519 §4.1.5). Skipped when the payload already
911
+ * carries an `nbf` claim.
912
+ *
913
+ * Mutually exclusive with {@link notBeforeIn}.
914
+ */
915
+ notBeforeAt?: Date;
574
916
  /** Additional JWE Protected Header parameters. */
575
917
  protectedHeader?: StrictOmit<JWEHeaderParameters, "alg" | "enc" | "iv" | "tag" | "p2s" | "p2c" | "epk" | "apu" | "apv">;
576
918
  /** Initialization Vector for AES-GCMKW key wrapping. Generated if not provided. */
@@ -629,6 +971,10 @@ interface JWEDecryptOptions extends JWTClaimValidationOptions {
629
971
  validateClaims?: boolean;
630
972
  /** If true, include the Content Encryption Key (CEK) and Additional Authenticated Data (AAD) in the result. */
631
973
  returnCek?: boolean;
974
+ /** Minimum accepted PBES2 `p2c` on unwrap. Defaults to 1000 (RFC 7518 §4.8.1.2). */
975
+ minIterations?: number;
976
+ /** Maximum accepted PBES2 `p2c` on unwrap. Defaults to 1_000_000 to cap PBKDF2 DoS potential. */
977
+ maxIterations?: number;
632
978
  }
633
979
  /**
634
980
  * JWE Protected Header — the parsed and validated protected header returned
@@ -654,9 +1000,120 @@ interface JWEDecryptResult<T extends JOSEPayload = JOSEPayload> {
654
1000
  /** The Additional Authenticated Data (AAD) used, as Uint8Array. Only present when `returnCek` is true. */
655
1001
  aad?: Uint8Array<ArrayBuffer>;
656
1002
  }
657
- //#endregion
658
- //#region src/core/types/index.d.ts
659
- type ExpiresIn = number | `${number}` | `${number}${"s" | "second" | "seconds" | "m" | "minute" | "minutes" | "h" | "hour" | "hours" | "D" | "day" | "days" | "W" | "week" | "weeks" | "M" | "month" | "months" | "Y" | "year" | "years"}`;
660
- type MaxTokenAge = ExpiresIn;
661
- //#endregion
662
- export { JWK_OKP_SIGN as $, JWK as A, JWK_AES_GCM_KW as B, DeriveKeyOptions as C, GenerateKeyAlgorithm as D, GenerateJWKReturn as E, JWKPEMAlgorithm as F, JWK_ECDH_ES as G, JWK_Asymmetric as H, JWKParameters as I, JWK_EC_Public as J, JWK_ECDSA as K, JWKSet as L, JWKCacheAdapter as M, JWKLookupFunction as N, GenerateKeyOptions as O, JWKLookupFunctionHeader as P, JWK_OKP_Public as Q, JWK_AES_CBC_HMAC as R, ContentEncryptionAlgorithm as S, GenerateJWKOptions as T, JWK_Asymmetric_Algorithm as U, JWK_AES_KW as V, JWK_EC as W, JWK_OKP as X, JWK_HMAC as Y, JWK_OKP_Private as Z, JWT as _, JWEEncryptOptions as a, JWK_RSA_ENC as at, JoseHeaderParameters as b, JWEProtectedHeader as c, JWK_RSA_Public as ct, JWSHeaderParameters as d, JWK_Symmetric_Algorithm as dt, JWK_PBES2 as et, JWSProtectedHeader as f, JWK_oct as ft, JOSEPayload as g, WrapKeyResult as gt, JWSVerifyResult as h, WrapKeyOptions as ht, JWEDecryptResult as i, JWK_RSA as it, JWKAlgorithm as j, GenerateKeyReturn as k, StrictOmit as l, JWK_RSA_SIGN as lt, JWSVerifyOptions as m, UnwrapKeyOptions as mt, MaxTokenAge as n, JWK_Private as nt, JWEHeaderParameters as o, JWK_RSA_PSS as ot, JWSSignOptions as p, KeyManagementAlgorithm as pt, JWK_EC_Private as q, JWEDecryptOptions as r, JWK_Public as rt, JWEKeyManagementHeaderParameters as s, JWK_RSA_Private as st, ExpiresIn as t, JWK_Pair as tt, JWSAlgorithm as u, JWK_Symmetric as ut, JWTClaimValidationOptions as v, DeriveKeyReturn as w, CompositeKey as x, JWTClaims as y, JWK_AES_GCM as z };
1003
+ /**
1004
+ * JWE Flattened JSON Serialization, RFC 7516 §7.2.2.
1005
+ */
1006
+ interface JWEFlattenedSerialization {
1007
+ header?: JWEHeaderParameters;
1008
+ encrypted_key?: string;
1009
+ /** Base64URL-encoded JWE Protected Header (part of AAD). */
1010
+ protected?: string;
1011
+ /** Shared JWE Unprotected Header (JSON, not part of AAD). */
1012
+ unprotected?: JWEHeaderParameters;
1013
+ /** Base64URL-encoded external Additional Authenticated Data. */
1014
+ aad?: string;
1015
+ /** Base64URL-encoded IV (Initialization Vector). */
1016
+ iv?: string;
1017
+ /** Base64URL-encoded ciphertext. */
1018
+ ciphertext: string;
1019
+ /** Base64URL-encoded authentication tag. */
1020
+ tag?: string;
1021
+ }
1022
+ /**
1023
+ * JWE General JSON Serialization, RFC 7516 §7.2.1. The canonical
1024
+ * multi-recipient output shape of {@link encryptMulti}.
1025
+ */
1026
+ interface JWEGeneralSerialization extends Omit<JWEFlattenedSerialization, "encrypted_key" | "header"> {
1027
+ /** One entry per recipient. */
1028
+ recipients: JWEGeneralRecipient[];
1029
+ }
1030
+ /** A single recipient entry within {@link JWEGeneralSerialization.recipients}. */
1031
+ interface JWEGeneralRecipient {
1032
+ /** Per-recipient JWE Unprotected Header (JSON, not part of AAD). */
1033
+ header?: JWEHeaderParameters;
1034
+ /** Base64URL-encoded encrypted CEK for this recipient. */
1035
+ encrypted_key?: string;
1036
+ }
1037
+ /**
1038
+ * Input shape for a single recipient passed to {@link encryptMulti}.
1039
+ *
1040
+ * `alg` is inferred from `key.alg` or from the JWK's kty/curve/length using
1041
+ * the same rules as {@link encrypt}. `kid` is pulled from `key.kid` when
1042
+ * present. To override either, spread or set via {@link JWEMultiRecipient.header}.
1043
+ */
1044
+ interface JWEMultiRecipient {
1045
+ /** Recipient key (JWK-first; `alg` inferred if absent from JWK). */
1046
+ key: JWEEncryptJWK;
1047
+ /**
1048
+ * Extra per-recipient JWE Unprotected Header parameters (RFC 7516 §7.2.1).
1049
+ * Excludes fields the library writes automatically: `alg`, `enc`, `iv`,
1050
+ * `tag`, `p2s`, `p2c`, `epk`, `apu`, `apv`.
1051
+ *
1052
+ * Typical use: `x5c`, `x5t`, custom routing metadata.
1053
+ */
1054
+ header?: StrictOmit<JWEHeaderParameters, "alg" | "enc" | "iv" | "tag" | "p2s" | "p2c" | "epk" | "apu" | "apv">;
1055
+ /** ECDH-ES ephemeral key / party info for this recipient. */
1056
+ ecdh?: JWEEncryptOptions["ecdh"];
1057
+ /** PBES2 salt for this recipient. Randomized (16 bytes) when omitted. */
1058
+ p2s?: Uint8Array<ArrayBuffer>;
1059
+ /** PBES2 iteration count for this recipient. Defaults to 600_000. */
1060
+ p2c?: number;
1061
+ /** Initialization vector for AES-GCMKW key wrapping for this recipient. */
1062
+ keyManagementIV?: Uint8Array<ArrayBuffer>;
1063
+ }
1064
+ /**
1065
+ * Options for {@link encryptMulti}. Extends {@link JWEEncryptOptions} and drops
1066
+ * the fields that are per-recipient in multi-recipient mode (`alg`, `ecdh`,
1067
+ * `p2s`, `p2c`, `keyManagementIV` — set those on each {@link JWEMultiRecipient}
1068
+ * instead).
1069
+ */
1070
+ interface JWEMultiEncryptOptions extends StrictOmit<JWEEncryptOptions, "alg" | "ecdh" | "p2s" | "p2c" | "keyManagementIV"> {
1071
+ /** Shared JWE Unprotected Header (surfaces as `unprotected` in the output). */
1072
+ sharedUnprotectedHeader?: Record<string, unknown>;
1073
+ /**
1074
+ * External Additional Authenticated Data (RFC 7516 §5.1). Encoded as
1075
+ * base64url and written to the `aad` field; the content cipher AAD becomes
1076
+ * `BASE64URL(protected) || '.' || BASE64URL(aad)`.
1077
+ */
1078
+ aad?: Uint8Array<ArrayBuffer> | string;
1079
+ }
1080
+ /**
1081
+ * Options for {@link decryptMulti}. Extends {@link JWEDecryptOptions}.
1082
+ */
1083
+ interface JWEMultiDecryptOptions extends JWEDecryptOptions {
1084
+ /**
1085
+ * When `false` (default) decryption trials recipients in order — mirrors the
1086
+ * multi-key retry behaviour of {@link decrypt} against a JWK Set. When
1087
+ * `true`, only recipients whose header unambiguously matches the provided
1088
+ * key (by `kid`, then by `kty`/`crv`/length) are attempted, and any mismatch
1089
+ * throws `ERR_JWE_NO_MATCHING_RECIPIENT` before any crypto work.
1090
+ */
1091
+ strictRecipientMatch?: boolean;
1092
+ }
1093
+ /**
1094
+ * Result of a {@link decryptMulti} operation. Extends {@link JWEDecryptResult}
1095
+ * with the per-recipient header tier surfaced on the matching recipient.
1096
+ */
1097
+ interface JWEMultiDecryptResult<T extends JOSEPayload = JOSEPayload> extends JWEDecryptResult<T> {
1098
+ /** Parsed shared unprotected header, when present on the serialization. */
1099
+ sharedUnprotectedHeader?: JWEHeaderParameters;
1100
+ /** Parsed per-recipient unprotected header of the recipient that decrypted. */
1101
+ recipientHeader?: JWEHeaderParameters;
1102
+ /** Index into `jwe.recipients` of the recipient that successfully decrypted. */
1103
+ recipientIndex: number;
1104
+ }
1105
+ /**
1106
+ * A time duration, expressed as an integer number of seconds or a human-readable
1107
+ * shorthand like `"10m"`, `"2h"`, `"7D"`.
1108
+ *
1109
+ * Shared base type for every duration-valued option in the library:
1110
+ * {@link ExpiresIn}, {@link NotBeforeIn}, {@link MaxTokenAge}.
1111
+ */
1112
+ type Duration = number | `${number}` | `${number}${"s" | "second" | "seconds" | "m" | "minute" | "minutes" | "h" | "hour" | "hours" | "D" | "day" | "days" | "W" | "week" | "weeks" | "M" | "month" | "months" | "Y" | "year" | "years"}`;
1113
+ /** Duration until `exp` — the `expiresIn` option on {@link sign} / {@link encrypt}. */
1114
+ type ExpiresIn = Duration;
1115
+ /** Duration from `iat` for `nbf` — the `notBeforeIn` option on {@link sign} / {@link encrypt}. */
1116
+ type NotBeforeIn = Duration;
1117
+ /** Duration for `maxTokenAge` validation on {@link verify} / {@link decrypt}. */
1118
+ type MaxTokenAge = Duration;
1119
+ export { DeriveKeyOptions as $, JWSMultiSigner as A, JWK_PBES2 as At, JWSVerifyResult as B, JWK_Symmetric as Bt, JWSAsymmetricPrivateJWK as C, JWK_EC_Private as Ct, JWSGeneralSignature as D, JWK_OKP_Private as Dt, JWSGeneralSerialization as E, JWK_OKP as Et, JWSProtectedHeader as F, JWK_RSA_ENC as Ft, isJWTError as G, UnwrappingKeyFor as Gt, JWTError as H, JWK_oct as Ht, JWSSignJWK as I, JWK_RSA_PSS as It, JWTClaimValidationOptions as J, WrappingKeyFor as Jt, JOSEPayload as K, WrapKeyOptions as Kt, JWSSignOptions as L, JWK_RSA_Private as Lt, JWSMultiVerifyOptions as M, JWK_Private as Mt, JWSMultiVerifyOutcome as N, JWK_Public as Nt, JWSHeaderParameters as O, JWK_OKP_Public as Ot, JWSMultiVerifyResult as P, JWK_RSA as Pt, ContentEncryptionAlgorithm as Q, JWSVerifyJWK as R, JWK_RSA_Public as Rt, JWSAlgorithm as S, JWK_ECDSA as St, JWSFlattenedSerialization as T, JWK_HMAC as Tt, JWTErrorCauseMap as U, KeyManagementAlgorithm as Ut, StrictOmit as V, JWK_Symmetric_Algorithm as Vt, JWTErrorCode as W, UnwrapKeyOptions as Wt, JoseHeaderParameters as X, JWTClaims as Y, CompositeKey as Z, JWEMultiDecryptOptions as _, JWK_AES_KW as _t, JWEAsymmetricPrivateJWK as a, GenerateKeyReturn as at, JWEMultiRecipient as b, JWK_EC as bt, JWEDecryptOptions as c, JWKCacheAdapter as ct, JWEEncryptOptions as d, JWKPEMAlgorithm as dt, DeriveKeyReturn as et, JWEFlattenedSerialization as f, JWKParameters as ft, JWEKeyManagementHeaderParameters as g, JWK_AES_GCM_KW as gt, JWEHeaderParameters as h, JWK_AES_GCM as ht, NotBeforeIn as i, GenerateKeyOptions as it, JWSMultiVerifyAllOptions as j, JWK_Pair as jt, JWSMultiSignOptions as k, JWK_OKP_SIGN as kt, JWEDecryptResult as l, JWKLookupFunction as lt, JWEGeneralSerialization as m, JWK_AES_CBC_HMAC as mt, ExpiresIn as n, GenerateJWKReturn as nt, JWEAsymmetricPublicJWK as o, JWK as ot, JWEGeneralRecipient as p, JWKSet as pt, JWT as q, WrapKeyResult as qt, MaxTokenAge as r, GenerateKeyAlgorithm as rt, JWEDecryptJWK as s, JWKAlgorithm as st, Duration as t, GenerateJWKOptions as tt, JWEEncryptJWK as u, JWKLookupFunctionHeader as ut, JWEMultiDecryptResult as v, JWK_Asymmetric as vt, JWSAsymmetricPublicJWK as w, JWK_EC_Public as wt, JWEProtectedHeader as x, JWK_ECDH_ES as xt, JWEMultiEncryptOptions as y, JWK_Asymmetric_Algorithm as yt, JWSVerifyOptions as z, JWK_RSA_SIGN as zt };