jose 5.7.0 → 5.9.0

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 (76) hide show
  1. package/README.md +21 -17
  2. package/dist/browser/jwe/flattened/encrypt.js +1 -1
  3. package/dist/browser/jwe/general/encrypt.js +2 -1
  4. package/dist/browser/jwks/local.js +1 -1
  5. package/dist/browser/jwks/remote.js +1 -1
  6. package/dist/browser/jws/flattened/sign.js +2 -2
  7. package/dist/browser/jws/flattened/verify.js +10 -2
  8. package/dist/browser/lib/check_key_type.js +40 -9
  9. package/dist/browser/lib/invalid_key_input.js +1 -0
  10. package/dist/browser/lib/is_jwk.js +13 -0
  11. package/dist/browser/lib/private_symbols.js +1 -0
  12. package/dist/browser/runtime/get_sign_verify_key.js +1 -1
  13. package/dist/browser/runtime/normalize_key.js +21 -4
  14. package/dist/node/cjs/jwe/flattened/encrypt.js +3 -3
  15. package/dist/node/cjs/jwe/general/encrypt.js +2 -1
  16. package/dist/node/cjs/jwks/local.js +1 -2
  17. package/dist/node/cjs/jwks/remote.js +1 -1
  18. package/dist/node/cjs/jws/flattened/sign.js +1 -1
  19. package/dist/node/cjs/jws/flattened/verify.js +9 -1
  20. package/dist/node/cjs/lib/check_key_type.js +41 -9
  21. package/dist/node/cjs/lib/invalid_key_input.js +1 -0
  22. package/dist/node/cjs/lib/is_jwk.js +20 -0
  23. package/dist/node/cjs/lib/private_symbols.js +4 -0
  24. package/dist/node/cjs/runtime/base64url.js +1 -1
  25. package/dist/node/cjs/runtime/check_key_length.js +11 -1
  26. package/dist/node/cjs/runtime/get_named_curve.js +4 -0
  27. package/dist/node/cjs/runtime/get_sign_verify_key.js +8 -1
  28. package/dist/node/cjs/runtime/node_key.js +51 -14
  29. package/dist/node/cjs/runtime/sign.js +3 -3
  30. package/dist/node/cjs/runtime/verify.js +3 -3
  31. package/dist/node/esm/jwe/flattened/encrypt.js +1 -1
  32. package/dist/node/esm/jwe/general/encrypt.js +2 -1
  33. package/dist/node/esm/jwks/local.js +1 -1
  34. package/dist/node/esm/jwks/remote.js +1 -1
  35. package/dist/node/esm/jws/flattened/sign.js +2 -2
  36. package/dist/node/esm/jws/flattened/verify.js +10 -2
  37. package/dist/node/esm/lib/check_key_type.js +40 -9
  38. package/dist/node/esm/lib/invalid_key_input.js +1 -0
  39. package/dist/node/esm/lib/is_jwk.js +13 -0
  40. package/dist/node/esm/lib/private_symbols.js +1 -0
  41. package/dist/node/esm/runtime/base64url.js +1 -1
  42. package/dist/node/esm/runtime/check_key_length.js +11 -1
  43. package/dist/node/esm/runtime/get_named_curve.js +4 -0
  44. package/dist/node/esm/runtime/get_sign_verify_key.js +8 -1
  45. package/dist/node/esm/runtime/node_key.js +52 -15
  46. package/dist/node/esm/runtime/sign.js +3 -3
  47. package/dist/node/esm/runtime/verify.js +3 -3
  48. package/dist/types/jwe/compact/decrypt.d.ts +3 -0
  49. package/dist/types/jwe/compact/encrypt.d.ts +3 -0
  50. package/dist/types/jwe/flattened/decrypt.d.ts +3 -0
  51. package/dist/types/jwe/flattened/encrypt.d.ts +3 -2
  52. package/dist/types/jwe/general/decrypt.d.ts +3 -0
  53. package/dist/types/jwe/general/encrypt.d.ts +3 -0
  54. package/dist/types/jwk/embedded.d.ts +3 -0
  55. package/dist/types/jwk/thumbprint.d.ts +6 -0
  56. package/dist/types/jwks/local.d.ts +3 -7
  57. package/dist/types/jwks/remote.d.ts +3 -0
  58. package/dist/types/jws/compact/sign.d.ts +5 -2
  59. package/dist/types/jws/compact/verify.d.ts +6 -3
  60. package/dist/types/jws/flattened/sign.d.ts +5 -2
  61. package/dist/types/jws/flattened/verify.d.ts +6 -3
  62. package/dist/types/jws/general/sign.d.ts +5 -2
  63. package/dist/types/jws/general/verify.d.ts +6 -3
  64. package/dist/types/jwt/decrypt.d.ts +3 -0
  65. package/dist/types/jwt/encrypt.d.ts +3 -0
  66. package/dist/types/jwt/sign.d.ts +5 -2
  67. package/dist/types/jwt/unsecured.d.ts +3 -0
  68. package/dist/types/jwt/verify.d.ts +6 -3
  69. package/dist/types/key/export.d.ts +9 -0
  70. package/dist/types/key/generate_key_pair.d.ts +3 -0
  71. package/dist/types/key/generate_secret.d.ts +3 -0
  72. package/dist/types/key/import.d.ts +12 -0
  73. package/dist/types/types.d.ts +129 -29
  74. package/dist/types/util/decode_jwt.d.ts +3 -0
  75. package/dist/types/util/decode_protected_header.d.ts +3 -0
  76. package/package.json +271 -1
package/README.md CHANGED
@@ -92,23 +92,6 @@ The following are additional features and utilities provided by the `jose` modul
92
92
  - [Unsecured JWT](docs/classes/jwt_unsecured.UnsecuredJWT.md)
93
93
  - [JOSE Errors](docs/modules/util_errors.md)
94
94
 
95
- ## Implemented specifications
96
-
97
- The `jose` module implements the following specifications:
98
-
99
- - JSON Web Signature (JWS) - [RFC7515](https://www.rfc-editor.org/rfc/rfc7515)
100
- - JSON Web Encryption (JWE) - [RFC7516](https://www.rfc-editor.org/rfc/rfc7516)
101
- - JSON Web Key (JWK) - [RFC7517](https://www.rfc-editor.org/rfc/rfc7517)
102
- - JSON Web Algorithms (JWA) - [RFC7518](https://www.rfc-editor.org/rfc/rfc7518)
103
- - JSON Web Token (JWT) - [RFC7519](https://www.rfc-editor.org/rfc/rfc7519)
104
- - JSON Web Key Thumbprint - [RFC7638](https://www.rfc-editor.org/rfc/rfc7638)
105
- - JSON Web Key Thumbprint URI - [RFC9278](https://www.rfc-editor.org/rfc/rfc9278)
106
- - JWS Unencoded Payload Option - [RFC7797](https://www.rfc-editor.org/rfc/rfc7797)
107
- - CFRG Elliptic Curve ECDH and Signatures - [RFC8037](https://www.rfc-editor.org/rfc/rfc8037)
108
- - secp256k1 EC Key curve support - [RFC8812](https://www.rfc-editor.org/rfc/rfc8812)
109
-
110
- The algorithm implementations have been tested using test vectors from their respective specifications as well as [RFC7520](https://www.rfc-editor.org/rfc/rfc7520).
111
-
112
95
  ## Supported Runtimes
113
96
 
114
97
  The `jose` module is compatible with JavaScript runtimes that support the utilized Web API globals and standard built-in objects or are Node.js.
@@ -131,3 +114,24 @@ Please note that certain algorithms may not be available depending on the runtim
131
114
  | [v5.x](https://github.com/panva/jose/tree/v5.x) | ✅ | ✅ | ✅ |
132
115
  | [v4.x](https://github.com/panva/jose/tree/v4.x) | ✅ | ❌ | ❌ |
133
116
  | [v2.x](https://github.com/panva/jose/tree/v2.x) | ✅ | ❌ | ❌ |
117
+
118
+ ## Specifications
119
+
120
+ <details>
121
+ <summary>Details</summary>
122
+
123
+ - JSON Web Signature (JWS) - [RFC7515](https://www.rfc-editor.org/rfc/rfc7515)
124
+ - JSON Web Encryption (JWE) - [RFC7516](https://www.rfc-editor.org/rfc/rfc7516)
125
+ - JSON Web Key (JWK) - [RFC7517](https://www.rfc-editor.org/rfc/rfc7517)
126
+ - JSON Web Algorithms (JWA) - [RFC7518](https://www.rfc-editor.org/rfc/rfc7518)
127
+ - JSON Web Token (JWT) - [RFC7519](https://www.rfc-editor.org/rfc/rfc7519)
128
+ - JSON Web Key Thumbprint - [RFC7638](https://www.rfc-editor.org/rfc/rfc7638)
129
+ - JSON Web Key Thumbprint URI - [RFC9278](https://www.rfc-editor.org/rfc/rfc9278)
130
+ - JWS Unencoded Payload Option - [RFC7797](https://www.rfc-editor.org/rfc/rfc7797)
131
+ - CFRG Elliptic Curve ECDH and Signatures - [RFC8037](https://www.rfc-editor.org/rfc/rfc8037)
132
+ - secp256k1 EC Key curve support - [RFC8812](https://www.rfc-editor.org/rfc/rfc8812)
133
+
134
+ The algorithm implementations in `jose` have been tested using test vectors from their respective specifications as well as [RFC7520](https://www.rfc-editor.org/rfc/rfc7520).
135
+
136
+
137
+ </details>
@@ -1,11 +1,11 @@
1
1
  import { encode as base64url } from '../../runtime/base64url.js';
2
+ import { unprotected } from '../../lib/private_symbols.js';
2
3
  import encrypt from '../../runtime/encrypt.js';
3
4
  import encryptKeyManagement from '../../lib/encrypt_key_management.js';
4
5
  import { JOSENotSupported, JWEInvalid } from '../../util/errors.js';
5
6
  import isDisjoint from '../../lib/is_disjoint.js';
6
7
  import { encoder, decoder, concat } from '../../lib/buffer_utils.js';
7
8
  import validateCrit from '../../lib/validate_crit.js';
8
- export const unprotected = Symbol();
9
9
  export class FlattenedEncrypt {
10
10
  constructor(plaintext) {
11
11
  if (!(plaintext instanceof Uint8Array)) {
@@ -1,4 +1,5 @@
1
- import { FlattenedEncrypt, unprotected } from '../flattened/encrypt.js';
1
+ import { FlattenedEncrypt } from '../flattened/encrypt.js';
2
+ import { unprotected } from '../../lib/private_symbols.js';
2
3
  import { JOSENotSupported, JWEInvalid } from '../../util/errors.js';
3
4
  import generateCek from '../../lib/cek.js';
4
5
  import isDisjoint from '../../lib/is_disjoint.js';
@@ -29,7 +29,7 @@ function clone(obj) {
29
29
  }
30
30
  return JSON.parse(JSON.stringify(obj));
31
31
  }
32
- export class LocalJWKSet {
32
+ class LocalJWKSet {
33
33
  constructor(jwks) {
34
34
  this._cached = new WeakMap();
35
35
  if (!isJWKSLike(jwks)) {
@@ -10,7 +10,7 @@ function isCloudflareWorkers() {
10
10
  let USER_AGENT;
11
11
  if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {
12
12
  const NAME = 'jose';
13
- const VERSION = 'v5.7.0';
13
+ const VERSION = 'v5.9.0';
14
14
  USER_AGENT = `${NAME}/${VERSION}`;
15
15
  }
16
16
  export const jwksCache = Symbol();
@@ -3,7 +3,7 @@ import sign from '../../runtime/sign.js';
3
3
  import isDisjoint from '../../lib/is_disjoint.js';
4
4
  import { JWSInvalid } from '../../util/errors.js';
5
5
  import { encoder, decoder, concat } from '../../lib/buffer_utils.js';
6
- import checkKeyType from '../../lib/check_key_type.js';
6
+ import { checkKeyTypeWithJwk } from '../../lib/check_key_type.js';
7
7
  import validateCrit from '../../lib/validate_crit.js';
8
8
  export class FlattenedSign {
9
9
  constructor(payload) {
@@ -49,7 +49,7 @@ export class FlattenedSign {
49
49
  if (typeof alg !== 'string' || !alg) {
50
50
  throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
51
51
  }
52
- checkKeyType(alg, key, 'sign');
52
+ checkKeyTypeWithJwk(alg, key, 'sign');
53
53
  let payload = this._payload;
54
54
  if (b64) {
55
55
  payload = encoder.encode(base64url(payload));
@@ -4,9 +4,11 @@ import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '.
4
4
  import { concat, encoder, decoder } from '../../lib/buffer_utils.js';
5
5
  import isDisjoint from '../../lib/is_disjoint.js';
6
6
  import isObject from '../../lib/is_object.js';
7
- import checkKeyType from '../../lib/check_key_type.js';
7
+ import { checkKeyTypeWithJwk } from '../../lib/check_key_type.js';
8
8
  import validateCrit from '../../lib/validate_crit.js';
9
9
  import validateAlgorithms from '../../lib/validate_algorithms.js';
10
+ import { isJWK } from '../../lib/is_jwk.js';
11
+ import { importJWK } from '../../key/import.js';
10
12
  export async function flattenedVerify(jws, key, options) {
11
13
  if (!isObject(jws)) {
12
14
  throw new JWSInvalid('Flattened JWS must be an object');
@@ -71,8 +73,14 @@ export async function flattenedVerify(jws, key, options) {
71
73
  if (typeof key === 'function') {
72
74
  key = await key(parsedProt, jws);
73
75
  resolvedKey = true;
76
+ checkKeyTypeWithJwk(alg, key, 'verify');
77
+ if (isJWK(key)) {
78
+ key = await importJWK(key, alg);
79
+ }
80
+ }
81
+ else {
82
+ checkKeyTypeWithJwk(alg, key, 'verify');
74
83
  }
75
- checkKeyType(alg, key, 'verify');
76
84
  const data = concat(encoder.encode(jws.protected ?? ''), encoder.encode('.'), typeof jws.payload === 'string' ? encoder.encode(jws.payload) : jws.payload);
77
85
  let signature;
78
86
  try {
@@ -1,19 +1,49 @@
1
1
  import { withAlg as invalidKeyInput } from './invalid_key_input.js';
2
2
  import isKeyLike, { types } from '../runtime/is_key_like.js';
3
+ import * as jwk from './is_jwk.js';
3
4
  const tag = (key) => key?.[Symbol.toStringTag];
4
- const symmetricTypeCheck = (alg, key) => {
5
+ const jwkMatchesOp = (alg, key, usage) => {
6
+ if (key.use !== undefined && key.use !== 'sig') {
7
+ throw new TypeError('Invalid key for this operation, when present its use must be sig');
8
+ }
9
+ if (key.key_ops !== undefined && key.key_ops.includes?.(usage) !== true) {
10
+ throw new TypeError(`Invalid key for this operation, when present its key_ops must include ${usage}`);
11
+ }
12
+ if (key.alg !== undefined && key.alg !== alg) {
13
+ throw new TypeError(`Invalid key for this operation, when present its alg must be ${alg}`);
14
+ }
15
+ return true;
16
+ };
17
+ const symmetricTypeCheck = (alg, key, usage, allowJwk) => {
5
18
  if (key instanceof Uint8Array)
6
19
  return;
20
+ if (allowJwk && jwk.isJWK(key)) {
21
+ if (jwk.isSecretJWK(key) && jwkMatchesOp(alg, key, usage))
22
+ return;
23
+ throw new TypeError(`JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present`);
24
+ }
7
25
  if (!isKeyLike(key)) {
8
- throw new TypeError(invalidKeyInput(alg, key, ...types, 'Uint8Array'));
26
+ throw new TypeError(invalidKeyInput(alg, key, ...types, 'Uint8Array', allowJwk ? 'JSON Web Key' : null));
9
27
  }
10
28
  if (key.type !== 'secret') {
11
29
  throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`);
12
30
  }
13
31
  };
14
- const asymmetricTypeCheck = (alg, key, usage) => {
32
+ const asymmetricTypeCheck = (alg, key, usage, allowJwk) => {
33
+ if (allowJwk && jwk.isJWK(key)) {
34
+ switch (usage) {
35
+ case 'sign':
36
+ if (jwk.isPrivateJWK(key) && jwkMatchesOp(alg, key, usage))
37
+ return;
38
+ throw new TypeError(`JSON Web Key for this operation be a private JWK`);
39
+ case 'verify':
40
+ if (jwk.isPublicJWK(key) && jwkMatchesOp(alg, key, usage))
41
+ return;
42
+ throw new TypeError(`JSON Web Key for this operation be a public JWK`);
43
+ }
44
+ }
15
45
  if (!isKeyLike(key)) {
16
- throw new TypeError(invalidKeyInput(alg, key, ...types));
46
+ throw new TypeError(invalidKeyInput(alg, key, ...types, allowJwk ? 'JSON Web Key' : null));
17
47
  }
18
48
  if (key.type === 'secret') {
19
49
  throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`);
@@ -31,16 +61,17 @@ const asymmetricTypeCheck = (alg, key, usage) => {
31
61
  throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type "public"`);
32
62
  }
33
63
  };
34
- const checkKeyType = (alg, key, usage) => {
64
+ function checkKeyType(allowJwk, alg, key, usage) {
35
65
  const symmetric = alg.startsWith('HS') ||
36
66
  alg === 'dir' ||
37
67
  alg.startsWith('PBES2') ||
38
68
  /^A\d{3}(?:GCM)?KW$/.test(alg);
39
69
  if (symmetric) {
40
- symmetricTypeCheck(alg, key);
70
+ symmetricTypeCheck(alg, key, usage, allowJwk);
41
71
  }
42
72
  else {
43
- asymmetricTypeCheck(alg, key, usage);
73
+ asymmetricTypeCheck(alg, key, usage, allowJwk);
44
74
  }
45
- };
46
- export default checkKeyType;
75
+ }
76
+ export default checkKeyType.bind(undefined, false);
77
+ export const checkKeyTypeWithJwk = checkKeyType.bind(undefined, true);
@@ -1,4 +1,5 @@
1
1
  function message(msg, actual, ...types) {
2
+ types = types.filter(Boolean);
2
3
  if (types.length > 2) {
3
4
  const last = types.pop();
4
5
  msg += `one of type ${types.join(', ')}, or ${last}.`;
@@ -0,0 +1,13 @@
1
+ import isObject from './is_object.js';
2
+ export function isJWK(key) {
3
+ return isObject(key) && typeof key.kty === 'string';
4
+ }
5
+ export function isPrivateJWK(key) {
6
+ return key.kty !== 'oct' && typeof key.d === 'string';
7
+ }
8
+ export function isPublicJWK(key) {
9
+ return key.kty !== 'oct' && typeof key.d === 'undefined';
10
+ }
11
+ export function isSecretJWK(key) {
12
+ return isJWK(key) && key.kty === 'oct' && typeof key.k === 'string';
13
+ }
@@ -0,0 +1 @@
1
+ export const unprotected = Symbol();
@@ -20,5 +20,5 @@ export default async function getCryptoKey(alg, key, usage) {
20
20
  }
21
21
  return crypto.subtle.importKey('raw', key, { hash: `SHA-${alg.slice(-3)}`, name: 'HMAC' }, false, [usage]);
22
22
  }
23
- throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array'));
23
+ throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array', 'JSON Web Key'));
24
24
  }
@@ -1,17 +1,20 @@
1
+ import { isJWK } from '../lib/is_jwk.js';
1
2
  import { decode } from './base64url.js';
2
3
  import importJWK from './jwk_to_key.js';
3
- const normalizeSecretKey = (k) => decode(k);
4
+ const exportKeyValue = (k) => decode(k);
4
5
  let privCache;
5
6
  let pubCache;
6
7
  const isKeyObject = (key) => {
7
8
  return key?.[Symbol.toStringTag] === 'KeyObject';
8
9
  };
9
- const importAndCache = async (cache, key, jwk, alg) => {
10
+ const importAndCache = async (cache, key, jwk, alg, freeze = false) => {
10
11
  let cached = cache.get(key);
11
12
  if (cached?.[alg]) {
12
13
  return cached[alg];
13
14
  }
14
15
  const cryptoKey = await importJWK({ ...jwk, alg });
16
+ if (freeze)
17
+ Object.freeze(key);
15
18
  if (!cached) {
16
19
  cache.set(key, { [alg]: cryptoKey });
17
20
  }
@@ -30,22 +33,36 @@ const normalizePublicKey = (key, alg) => {
30
33
  delete jwk.q;
31
34
  delete jwk.qi;
32
35
  if (jwk.k) {
33
- return normalizeSecretKey(jwk.k);
36
+ return exportKeyValue(jwk.k);
34
37
  }
35
38
  pubCache || (pubCache = new WeakMap());
36
39
  return importAndCache(pubCache, key, jwk, alg);
37
40
  }
41
+ if (isJWK(key)) {
42
+ if (key.k)
43
+ return decode(key.k);
44
+ pubCache || (pubCache = new WeakMap());
45
+ const cryptoKey = importAndCache(pubCache, key, key, alg, true);
46
+ return cryptoKey;
47
+ }
38
48
  return key;
39
49
  };
40
50
  const normalizePrivateKey = (key, alg) => {
41
51
  if (isKeyObject(key)) {
42
52
  let jwk = key.export({ format: 'jwk' });
43
53
  if (jwk.k) {
44
- return normalizeSecretKey(jwk.k);
54
+ return exportKeyValue(jwk.k);
45
55
  }
46
56
  privCache || (privCache = new WeakMap());
47
57
  return importAndCache(privCache, key, jwk, alg);
48
58
  }
59
+ if (isJWK(key)) {
60
+ if (key.k)
61
+ return decode(key.k);
62
+ privCache || (privCache = new WeakMap());
63
+ const cryptoKey = importAndCache(privCache, key, key, alg, true);
64
+ return cryptoKey;
65
+ }
49
66
  return key;
50
67
  };
51
68
  export default { normalizePublicKey, normalizePrivateKey };
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FlattenedEncrypt = exports.unprotected = void 0;
3
+ exports.FlattenedEncrypt = void 0;
4
4
  const base64url_js_1 = require("../../runtime/base64url.js");
5
+ const private_symbols_js_1 = require("../../lib/private_symbols.js");
5
6
  const encrypt_js_1 = require("../../runtime/encrypt.js");
6
7
  const encrypt_key_management_js_1 = require("../../lib/encrypt_key_management.js");
7
8
  const errors_js_1 = require("../../util/errors.js");
8
9
  const is_disjoint_js_1 = require("../../lib/is_disjoint.js");
9
10
  const buffer_utils_js_1 = require("../../lib/buffer_utils.js");
10
11
  const validate_crit_js_1 = require("../../lib/validate_crit.js");
11
- exports.unprotected = Symbol();
12
12
  class FlattenedEncrypt {
13
13
  _plaintext;
14
14
  _protectedHeader;
@@ -102,7 +102,7 @@ class FlattenedEncrypt {
102
102
  let parameters;
103
103
  ({ cek, encryptedKey, parameters } = await (0, encrypt_key_management_js_1.default)(alg, enc, key, this._cek, this._keyManagementParameters));
104
104
  if (parameters) {
105
- if (options && exports.unprotected in options) {
105
+ if (options && private_symbols_js_1.unprotected in options) {
106
106
  if (!this._unprotectedHeader) {
107
107
  this.setUnprotectedHeader(parameters);
108
108
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GeneralEncrypt = void 0;
4
4
  const encrypt_js_1 = require("../flattened/encrypt.js");
5
+ const private_symbols_js_1 = require("../../lib/private_symbols.js");
5
6
  const errors_js_1 = require("../../util/errors.js");
6
7
  const cek_js_1 = require("../../lib/cek.js");
7
8
  const is_disjoint_js_1 = require("../../lib/is_disjoint.js");
@@ -156,7 +157,7 @@ class GeneralEncrypt {
156
157
  .setKeyManagementParameters({ p2c })
157
158
  .encrypt(recipient.key, {
158
159
  ...recipient.options,
159
- [encrypt_js_1.unprotected]: true,
160
+ [private_symbols_js_1.unprotected]: true,
160
161
  });
161
162
  jwe.ciphertext = flattened.ciphertext;
162
163
  jwe.iv = flattened.iv;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createLocalJWKSet = exports.LocalJWKSet = void 0;
3
+ exports.createLocalJWKSet = void 0;
4
4
  const import_js_1 = require("../key/import.js");
5
5
  const errors_js_1 = require("../util/errors.js");
6
6
  const is_object_js_1 = require("../lib/is_object.js");
@@ -99,7 +99,6 @@ class LocalJWKSet {
99
99
  return importWithAlgCache(this._cached, jwk, alg);
100
100
  }
101
101
  }
102
- exports.LocalJWKSet = LocalJWKSet;
103
102
  async function importWithAlgCache(cache, jwk, alg) {
104
103
  const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk);
105
104
  if (cached[alg] === undefined) {
@@ -13,7 +13,7 @@ function isCloudflareWorkers() {
13
13
  let USER_AGENT;
14
14
  if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {
15
15
  const NAME = 'jose';
16
- const VERSION = 'v5.7.0';
16
+ const VERSION = 'v5.9.0';
17
17
  USER_AGENT = `${NAME}/${VERSION}`;
18
18
  }
19
19
  exports.jwksCache = Symbol();
@@ -55,7 +55,7 @@ class FlattenedSign {
55
55
  if (typeof alg !== 'string' || !alg) {
56
56
  throw new errors_js_1.JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
57
57
  }
58
- (0, check_key_type_js_1.default)(alg, key, 'sign');
58
+ (0, check_key_type_js_1.checkKeyTypeWithJwk)(alg, key, 'sign');
59
59
  let payload = this._payload;
60
60
  if (b64) {
61
61
  payload = buffer_utils_js_1.encoder.encode((0, base64url_js_1.encode)(payload));
@@ -10,6 +10,8 @@ const is_object_js_1 = require("../../lib/is_object.js");
10
10
  const check_key_type_js_1 = require("../../lib/check_key_type.js");
11
11
  const validate_crit_js_1 = require("../../lib/validate_crit.js");
12
12
  const validate_algorithms_js_1 = require("../../lib/validate_algorithms.js");
13
+ const is_jwk_js_1 = require("../../lib/is_jwk.js");
14
+ const import_js_1 = require("../../key/import.js");
13
15
  async function flattenedVerify(jws, key, options) {
14
16
  if (!(0, is_object_js_1.default)(jws)) {
15
17
  throw new errors_js_1.JWSInvalid('Flattened JWS must be an object');
@@ -74,8 +76,14 @@ async function flattenedVerify(jws, key, options) {
74
76
  if (typeof key === 'function') {
75
77
  key = await key(parsedProt, jws);
76
78
  resolvedKey = true;
79
+ (0, check_key_type_js_1.checkKeyTypeWithJwk)(alg, key, 'verify');
80
+ if ((0, is_jwk_js_1.isJWK)(key)) {
81
+ key = await (0, import_js_1.importJWK)(key, alg);
82
+ }
83
+ }
84
+ else {
85
+ (0, check_key_type_js_1.checkKeyTypeWithJwk)(alg, key, 'verify');
77
86
  }
78
- (0, check_key_type_js_1.default)(alg, key, 'verify');
79
87
  const data = (0, buffer_utils_js_1.concat)(buffer_utils_js_1.encoder.encode(jws.protected ?? ''), buffer_utils_js_1.encoder.encode('.'), typeof jws.payload === 'string' ? buffer_utils_js_1.encoder.encode(jws.payload) : jws.payload);
80
88
  let signature;
81
89
  try {
@@ -1,21 +1,52 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkKeyTypeWithJwk = void 0;
3
4
  const invalid_key_input_js_1 = require("./invalid_key_input.js");
4
5
  const is_key_like_js_1 = require("../runtime/is_key_like.js");
6
+ const jwk = require("./is_jwk.js");
5
7
  const tag = (key) => key?.[Symbol.toStringTag];
6
- const symmetricTypeCheck = (alg, key) => {
8
+ const jwkMatchesOp = (alg, key, usage) => {
9
+ if (key.use !== undefined && key.use !== 'sig') {
10
+ throw new TypeError('Invalid key for this operation, when present its use must be sig');
11
+ }
12
+ if (key.key_ops !== undefined && key.key_ops.includes?.(usage) !== true) {
13
+ throw new TypeError(`Invalid key for this operation, when present its key_ops must include ${usage}`);
14
+ }
15
+ if (key.alg !== undefined && key.alg !== alg) {
16
+ throw new TypeError(`Invalid key for this operation, when present its alg must be ${alg}`);
17
+ }
18
+ return true;
19
+ };
20
+ const symmetricTypeCheck = (alg, key, usage, allowJwk) => {
7
21
  if (key instanceof Uint8Array)
8
22
  return;
23
+ if (allowJwk && jwk.isJWK(key)) {
24
+ if (jwk.isSecretJWK(key) && jwkMatchesOp(alg, key, usage))
25
+ return;
26
+ throw new TypeError(`JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present`);
27
+ }
9
28
  if (!(0, is_key_like_js_1.default)(key)) {
10
- throw new TypeError((0, invalid_key_input_js_1.withAlg)(alg, key, ...is_key_like_js_1.types, 'Uint8Array'));
29
+ throw new TypeError((0, invalid_key_input_js_1.withAlg)(alg, key, ...is_key_like_js_1.types, 'Uint8Array', allowJwk ? 'JSON Web Key' : null));
11
30
  }
12
31
  if (key.type !== 'secret') {
13
32
  throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`);
14
33
  }
15
34
  };
16
- const asymmetricTypeCheck = (alg, key, usage) => {
35
+ const asymmetricTypeCheck = (alg, key, usage, allowJwk) => {
36
+ if (allowJwk && jwk.isJWK(key)) {
37
+ switch (usage) {
38
+ case 'sign':
39
+ if (jwk.isPrivateJWK(key) && jwkMatchesOp(alg, key, usage))
40
+ return;
41
+ throw new TypeError(`JSON Web Key for this operation be a private JWK`);
42
+ case 'verify':
43
+ if (jwk.isPublicJWK(key) && jwkMatchesOp(alg, key, usage))
44
+ return;
45
+ throw new TypeError(`JSON Web Key for this operation be a public JWK`);
46
+ }
47
+ }
17
48
  if (!(0, is_key_like_js_1.default)(key)) {
18
- throw new TypeError((0, invalid_key_input_js_1.withAlg)(alg, key, ...is_key_like_js_1.types));
49
+ throw new TypeError((0, invalid_key_input_js_1.withAlg)(alg, key, ...is_key_like_js_1.types, allowJwk ? 'JSON Web Key' : null));
19
50
  }
20
51
  if (key.type === 'secret') {
21
52
  throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`);
@@ -33,16 +64,17 @@ const asymmetricTypeCheck = (alg, key, usage) => {
33
64
  throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type "public"`);
34
65
  }
35
66
  };
36
- const checkKeyType = (alg, key, usage) => {
67
+ function checkKeyType(allowJwk, alg, key, usage) {
37
68
  const symmetric = alg.startsWith('HS') ||
38
69
  alg === 'dir' ||
39
70
  alg.startsWith('PBES2') ||
40
71
  /^A\d{3}(?:GCM)?KW$/.test(alg);
41
72
  if (symmetric) {
42
- symmetricTypeCheck(alg, key);
73
+ symmetricTypeCheck(alg, key, usage, allowJwk);
43
74
  }
44
75
  else {
45
- asymmetricTypeCheck(alg, key, usage);
76
+ asymmetricTypeCheck(alg, key, usage, allowJwk);
46
77
  }
47
- };
48
- exports.default = checkKeyType;
78
+ }
79
+ exports.default = checkKeyType.bind(undefined, false);
80
+ exports.checkKeyTypeWithJwk = checkKeyType.bind(undefined, true);
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.withAlg = void 0;
4
4
  function message(msg, actual, ...types) {
5
+ types = types.filter(Boolean);
5
6
  if (types.length > 2) {
6
7
  const last = types.pop();
7
8
  msg += `one of type ${types.join(', ')}, or ${last}.`;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSecretJWK = exports.isPublicJWK = exports.isPrivateJWK = exports.isJWK = void 0;
4
+ const is_object_js_1 = require("./is_object.js");
5
+ function isJWK(key) {
6
+ return (0, is_object_js_1.default)(key) && typeof key.kty === 'string';
7
+ }
8
+ exports.isJWK = isJWK;
9
+ function isPrivateJWK(key) {
10
+ return key.kty !== 'oct' && typeof key.d === 'string';
11
+ }
12
+ exports.isPrivateJWK = isPrivateJWK;
13
+ function isPublicJWK(key) {
14
+ return key.kty !== 'oct' && typeof key.d === 'undefined';
15
+ }
16
+ exports.isPublicJWK = isPublicJWK;
17
+ function isSecretJWK(key) {
18
+ return isJWK(key) && key.kty === 'oct' && typeof key.k === 'string';
19
+ }
20
+ exports.isSecretJWK = isSecretJWK;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unprotected = void 0;
4
+ exports.unprotected = Symbol();
@@ -16,5 +16,5 @@ const decodeBase64 = (input) => new Uint8Array(node_buffer_1.Buffer.from(input,
16
16
  exports.decodeBase64 = decodeBase64;
17
17
  const encodeBase64 = (input) => node_buffer_1.Buffer.from(input).toString('base64');
18
18
  exports.encodeBase64 = encodeBase64;
19
- const decode = (input) => new Uint8Array(node_buffer_1.Buffer.from(normalize(input), 'base64'));
19
+ const decode = (input) => new Uint8Array(node_buffer_1.Buffer.from(normalize(input), 'base64url'));
20
20
  exports.decode = decode;
@@ -1,7 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const node_crypto_1 = require("node:crypto");
3
4
  exports.default = (key, alg) => {
4
- const { modulusLength } = key.asymmetricKeyDetails;
5
+ let modulusLength;
6
+ try {
7
+ if (key instanceof node_crypto_1.KeyObject) {
8
+ modulusLength = key.asymmetricKeyDetails?.modulusLength;
9
+ }
10
+ else {
11
+ modulusLength = Buffer.from(key.n, 'base64url').byteLength << 3;
12
+ }
13
+ }
14
+ catch { }
5
15
  if (typeof modulusLength !== 'number' || modulusLength < 2048) {
6
16
  throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);
7
17
  }
@@ -7,6 +7,7 @@ const webcrypto_js_1 = require("./webcrypto.js");
7
7
  const is_key_object_js_1 = require("./is_key_object.js");
8
8
  const invalid_key_input_js_1 = require("../lib/invalid_key_input.js");
9
9
  const is_key_like_js_1 = require("./is_key_like.js");
10
+ const is_jwk_js_1 = require("../lib/is_jwk.js");
10
11
  exports.weakMap = new WeakMap();
11
12
  const namedCurveToJOSE = (namedCurve) => {
12
13
  switch (namedCurve) {
@@ -30,6 +31,9 @@ const getNamedCurve = (kee, raw) => {
30
31
  else if ((0, is_key_object_js_1.default)(kee)) {
31
32
  key = kee;
32
33
  }
34
+ else if ((0, is_jwk_js_1.isJWK)(kee)) {
35
+ return kee.crv;
36
+ }
33
37
  else {
34
38
  throw new TypeError((0, invalid_key_input_js_1.default)(kee, ...is_key_like_js_1.types));
35
39
  }
@@ -5,6 +5,7 @@ const webcrypto_js_1 = require("./webcrypto.js");
5
5
  const crypto_key_js_1 = require("../lib/crypto_key.js");
6
6
  const invalid_key_input_js_1 = require("../lib/invalid_key_input.js");
7
7
  const is_key_like_js_1 = require("./is_key_like.js");
8
+ const jwk = require("../lib/is_jwk.js");
8
9
  function getSignVerifyKey(alg, key, usage) {
9
10
  if (key instanceof Uint8Array) {
10
11
  if (!alg.startsWith('HS')) {
@@ -19,6 +20,12 @@ function getSignVerifyKey(alg, key, usage) {
19
20
  (0, crypto_key_js_1.checkSigCryptoKey)(key, alg, usage);
20
21
  return node_crypto_1.KeyObject.from(key);
21
22
  }
22
- throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types, 'Uint8Array'));
23
+ if (jwk.isJWK(key)) {
24
+ if (alg.startsWith('HS')) {
25
+ return (0, node_crypto_1.createSecretKey)(Buffer.from(key.k, 'base64url'));
26
+ }
27
+ return key;
28
+ }
29
+ throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types, 'Uint8Array', 'JSON Web Key'));
23
30
  }
24
31
  exports.default = getSignVerifyKey;