jose 3.17.0 → 3.20.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.
Files changed (103) hide show
  1. package/README.md +10 -3
  2. package/dist/browser/jwe/compact/decrypt.js +5 -1
  3. package/dist/browser/jwe/flattened/decrypt.js +5 -0
  4. package/dist/browser/jwk/embedded.js +3 -3
  5. package/dist/browser/jwk/from_key_like.js +2 -2
  6. package/dist/browser/jwk/parse.js +2 -31
  7. package/dist/browser/jwks/remote.js +7 -10
  8. package/dist/browser/jws/compact/verify.js +5 -1
  9. package/dist/browser/jws/flattened/verify.js +5 -0
  10. package/dist/browser/jwt/decrypt.js +5 -1
  11. package/dist/browser/jwt/encrypt.js +1 -1
  12. package/dist/browser/{lib/jwt_producer.js → jwt/produce.js} +4 -4
  13. package/dist/browser/jwt/sign.js +1 -1
  14. package/dist/browser/jwt/unsecured.js +1 -1
  15. package/dist/browser/jwt/verify.js +5 -1
  16. package/dist/browser/key/export.js +12 -0
  17. package/dist/browser/key/import.js +119 -0
  18. package/dist/browser/lib/check_key_type.js +33 -16
  19. package/dist/browser/lib/decrypt_key_management.js +37 -37
  20. package/dist/browser/lib/encrypt_key_management.js +2 -2
  21. package/dist/browser/lib/format_pem.js +4 -0
  22. package/dist/browser/runtime/asn1.js +119 -0
  23. package/dist/browser/runtime/base64url.js +12 -7
  24. package/dist/browser/runtime/fetch_jwks.js +18 -5
  25. package/dist/browser/runtime/is_key_like.js +5 -0
  26. package/dist/browser/util/errors.js +10 -3
  27. package/dist/node/cjs/jwe/compact/decrypt.js +5 -1
  28. package/dist/node/cjs/jwe/flattened/decrypt.js +5 -0
  29. package/dist/node/cjs/jwk/embedded.js +3 -3
  30. package/dist/node/cjs/jwk/from_key_like.js +2 -2
  31. package/dist/node/cjs/jwk/parse.js +2 -31
  32. package/dist/node/cjs/jwks/remote.js +7 -10
  33. package/dist/node/cjs/jws/compact/verify.js +5 -1
  34. package/dist/node/cjs/jws/flattened/verify.js +5 -0
  35. package/dist/node/cjs/jwt/decrypt.js +5 -1
  36. package/dist/node/cjs/jwt/encrypt.js +2 -2
  37. package/dist/node/cjs/{lib/jwt_producer.js → jwt/produce.js} +5 -4
  38. package/dist/node/cjs/jwt/sign.js +2 -2
  39. package/dist/node/cjs/jwt/unsecured.js +2 -2
  40. package/dist/node/cjs/jwt/verify.js +5 -1
  41. package/dist/node/cjs/key/export.js +18 -0
  42. package/dist/node/cjs/key/import.js +126 -0
  43. package/dist/node/cjs/lib/check_key_type.js +33 -16
  44. package/dist/node/cjs/lib/decrypt_key_management.js +37 -37
  45. package/dist/node/cjs/lib/encrypt_key_management.js +2 -2
  46. package/dist/node/cjs/lib/format_pem.js +6 -0
  47. package/dist/node/cjs/runtime/asn1.js +46 -0
  48. package/dist/node/cjs/runtime/base64url.js +5 -1
  49. package/dist/node/cjs/runtime/fetch_jwks.js +5 -1
  50. package/dist/node/cjs/runtime/is_key_like.js +11 -0
  51. package/dist/node/cjs/util/errors.js +12 -4
  52. package/dist/node/esm/jwe/compact/decrypt.js +5 -1
  53. package/dist/node/esm/jwe/flattened/decrypt.js +5 -0
  54. package/dist/node/esm/jwk/embedded.js +3 -3
  55. package/dist/node/esm/jwk/from_key_like.js +2 -2
  56. package/dist/node/esm/jwk/parse.js +2 -31
  57. package/dist/node/esm/jwks/remote.js +7 -10
  58. package/dist/node/esm/jws/compact/verify.js +5 -1
  59. package/dist/node/esm/jws/flattened/verify.js +5 -0
  60. package/dist/node/esm/jwt/decrypt.js +5 -1
  61. package/dist/node/esm/jwt/encrypt.js +1 -1
  62. package/dist/node/esm/{lib/jwt_producer.js → jwt/produce.js} +4 -4
  63. package/dist/node/esm/jwt/sign.js +1 -1
  64. package/dist/node/esm/jwt/unsecured.js +1 -1
  65. package/dist/node/esm/jwt/verify.js +5 -1
  66. package/dist/node/esm/key/export.js +12 -0
  67. package/dist/node/esm/key/import.js +119 -0
  68. package/dist/node/esm/lib/check_key_type.js +33 -16
  69. package/dist/node/esm/lib/decrypt_key_management.js +37 -37
  70. package/dist/node/esm/lib/encrypt_key_management.js +2 -2
  71. package/dist/node/esm/lib/format_pem.js +4 -0
  72. package/dist/node/esm/runtime/asn1.js +39 -0
  73. package/dist/node/esm/runtime/base64url.js +2 -0
  74. package/dist/node/esm/runtime/fetch_jwks.js +6 -2
  75. package/dist/node/esm/runtime/is_key_like.js +8 -0
  76. package/dist/node/esm/util/errors.js +10 -3
  77. package/dist/types/jwe/compact/decrypt.d.ts +3 -2
  78. package/dist/types/jwe/compact/encrypt.d.ts +1 -1
  79. package/dist/types/jwe/flattened/decrypt.d.ts +3 -2
  80. package/dist/types/jwe/flattened/encrypt.d.ts +1 -1
  81. package/dist/types/jwe/general/decrypt.d.ts +3 -2
  82. package/dist/types/jwk/embedded.d.ts +2 -3
  83. package/dist/types/jwk/from_key_like.d.ts +1 -1
  84. package/dist/types/jwk/parse.d.ts +1 -1
  85. package/dist/types/jws/compact/sign.d.ts +1 -1
  86. package/dist/types/jws/compact/verify.d.ts +3 -2
  87. package/dist/types/jws/flattened/sign.d.ts +1 -1
  88. package/dist/types/jws/flattened/verify.d.ts +3 -2
  89. package/dist/types/jws/general/sign.d.ts +1 -1
  90. package/dist/types/jws/general/verify.d.ts +3 -2
  91. package/dist/types/jwt/decrypt.d.ts +3 -2
  92. package/dist/types/jwt/encrypt.d.ts +2 -2
  93. package/dist/types/{lib/jwt_producer.d.ts → jwt/produce.d.ts} +1 -1
  94. package/dist/types/jwt/sign.d.ts +2 -2
  95. package/dist/types/jwt/unsecured.d.ts +1 -1
  96. package/dist/types/jwt/verify.d.ts +3 -2
  97. package/dist/types/key/export.d.ts +5 -0
  98. package/dist/types/key/import.d.ts +9 -0
  99. package/dist/types/types.d.ts +101 -5
  100. package/dist/types/util/errors.d.ts +5 -0
  101. package/dist/types/util/generate_key_pair.d.ts +2 -2
  102. package/dist/types/util/generate_secret.d.ts +1 -1
  103. package/package.json +20 -8
@@ -0,0 +1,119 @@
1
+ import globalThis, { isCloudflareWorkers, isNodeJs } from './global.js';
2
+ import crypto, { isCryptoKey } from './webcrypto.js';
3
+ import invalidKeyInput from './invalid_key_input.js';
4
+ import { encodeBase64 } from './base64url.js';
5
+ import formatPEM from '../lib/format_pem.js';
6
+ import { JOSENotSupported } from '../util/errors.js';
7
+ const genericExport = async (keyType, keyFormat, key) => {
8
+ if (!isCryptoKey(key)) {
9
+ throw new TypeError(invalidKeyInput(key, 'CryptoKey'));
10
+ }
11
+ if (!key.extractable) {
12
+ throw new TypeError('CryptoKey is not extractable');
13
+ }
14
+ if (key.type !== keyType) {
15
+ throw new TypeError(`key is not a ${keyType} key`);
16
+ }
17
+ return formatPEM(encodeBase64(new Uint8Array(await crypto.subtle.exportKey(keyFormat, key))), `${keyType.toUpperCase()} KEY`);
18
+ };
19
+ export const toSPKI = (key) => {
20
+ return genericExport('public', 'spki', key);
21
+ };
22
+ export const toPKCS8 = (key) => {
23
+ return genericExport('private', 'pkcs8', key);
24
+ };
25
+ const getNamedCurve = (keyData) => {
26
+ const keyDataStr = keyData.toString();
27
+ switch (true) {
28
+ case keyDataStr.includes(new Uint8Array([
29
+ 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
30
+ 0x3d, 0x03, 0x01, 0x07,
31
+ ]).toString()):
32
+ return 'P-256';
33
+ case keyDataStr.includes(new Uint8Array([
34
+ 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00,
35
+ 0x22,
36
+ ]).toString()):
37
+ return 'P-384';
38
+ case keyDataStr.includes(new Uint8Array([
39
+ 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00,
40
+ 0x23,
41
+ ]).toString()):
42
+ return 'P-521';
43
+ case (isCloudflareWorkers() || isNodeJs()) &&
44
+ keyDataStr.includes(new Uint8Array([0x06, 0x03, 0x2b, 0x65, 0x70]).toString()):
45
+ return 'Ed25519';
46
+ case isNodeJs() &&
47
+ keyDataStr.includes(new Uint8Array([0x06, 0x03, 0x2b, 0x65, 0x71]).toString()):
48
+ return 'Ed448';
49
+ default:
50
+ throw new JOSENotSupported('Invalid or unsupported EC Key Curve or OKP Key Sub Type');
51
+ }
52
+ };
53
+ const genericImport = async (replace, keyFormat, pem, alg, options) => {
54
+ var _a;
55
+ let algorithm;
56
+ let keyUsages;
57
+ const keyData = new Uint8Array(globalThis
58
+ .atob(pem.replace(replace, ''))
59
+ .split('')
60
+ .map((c) => c.charCodeAt(0)));
61
+ const isPublic = keyFormat === 'spki';
62
+ switch (alg) {
63
+ case 'PS256':
64
+ case 'PS384':
65
+ case 'PS512':
66
+ algorithm = { name: 'RSA-PSS', hash: { name: `SHA-${alg.substr(-3)}` } };
67
+ keyUsages = isPublic ? ['verify'] : ['sign'];
68
+ break;
69
+ case 'RS256':
70
+ case 'RS384':
71
+ case 'RS512':
72
+ algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: { name: `SHA-${alg.substr(-3)}` } };
73
+ keyUsages = isPublic ? ['verify'] : ['sign'];
74
+ break;
75
+ case 'RSA-OAEP':
76
+ case 'RSA-OAEP-256':
77
+ case 'RSA-OAEP-384':
78
+ case 'RSA-OAEP-512':
79
+ algorithm = {
80
+ name: 'RSA-OAEP',
81
+ hash: { name: `SHA-${parseInt(alg.substr(-3), 10) || 1}` },
82
+ };
83
+ keyUsages = isPublic ? ['encrypt', 'wrapKey'] : ['decrypt', 'unwrapKey'];
84
+ break;
85
+ case 'ES256':
86
+ algorithm = { name: 'ECDSA', namedCurve: 'P-256' };
87
+ keyUsages = isPublic ? ['verify'] : ['sign'];
88
+ break;
89
+ case 'ES384':
90
+ algorithm = { name: 'ECDSA', namedCurve: 'P-384' };
91
+ keyUsages = isPublic ? ['verify'] : ['sign'];
92
+ break;
93
+ case 'ES512':
94
+ algorithm = { name: 'ECDSA', namedCurve: 'P-521' };
95
+ keyUsages = isPublic ? ['verify'] : ['sign'];
96
+ break;
97
+ case 'ECDH-ES':
98
+ case 'ECDH-ES+A128KW':
99
+ case 'ECDH-ES+A192KW':
100
+ case 'ECDH-ES+A256KW':
101
+ algorithm = { name: 'ECDH', namedCurve: getNamedCurve(keyData) };
102
+ keyUsages = isPublic ? [] : ['deriveBits'];
103
+ break;
104
+ case (isCloudflareWorkers() || isNodeJs()) && 'EdDSA':
105
+ const namedCurve = getNamedCurve(keyData).toUpperCase();
106
+ algorithm = { name: `NODE-${namedCurve}`, namedCurve: `NODE-${namedCurve}` };
107
+ keyUsages = isPublic ? ['verify'] : ['sign'];
108
+ break;
109
+ default:
110
+ throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value');
111
+ }
112
+ return crypto.subtle.importKey(keyFormat, keyData, algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages);
113
+ };
114
+ export const fromPKCS8 = (pem, alg, options) => {
115
+ return genericImport(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, 'pkcs8', pem, alg, options);
116
+ };
117
+ export const fromSPKI = (pem, alg, options) => {
118
+ return genericImport(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, 'spki', pem, alg, options);
119
+ };
@@ -1,6 +1,6 @@
1
1
  import { encoder, decoder } from '../lib/buffer_utils.js';
2
2
  import globalThis from './global.js';
3
- export const encode = (input) => {
3
+ export const encodeBase64 = (input) => {
4
4
  let unencoded = input;
5
5
  if (typeof unencoded === 'string') {
6
6
  unencoded = encoder.encode(unencoded);
@@ -10,8 +10,16 @@ export const encode = (input) => {
10
10
  for (let i = 0; i < unencoded.length; i += CHUNK_SIZE) {
11
11
  arr.push(String.fromCharCode.apply(null, unencoded.subarray(i, i + CHUNK_SIZE)));
12
12
  }
13
- const base64string = globalThis.btoa(arr.join(''));
14
- return base64string.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
13
+ return globalThis.btoa(arr.join(''));
14
+ };
15
+ export const encode = (input) => {
16
+ return encodeBase64(input).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
17
+ };
18
+ export const decodeBase64 = (encoded) => {
19
+ return new Uint8Array(globalThis
20
+ .atob(encoded)
21
+ .split('')
22
+ .map((c) => c.charCodeAt(0)));
15
23
  };
16
24
  export const decode = (input) => {
17
25
  let encoded = input;
@@ -20,10 +28,7 @@ export const decode = (input) => {
20
28
  }
21
29
  encoded = encoded.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '');
22
30
  try {
23
- return new Uint8Array(globalThis
24
- .atob(encoded)
25
- .split('')
26
- .map((c) => c.charCodeAt(0)));
31
+ return decodeBase64(encoded);
27
32
  }
28
33
  catch (_a) {
29
34
  throw new TypeError('The input to be decoded is not correctly encoded.');
@@ -1,23 +1,36 @@
1
- import { JOSEError } from '../util/errors.js';
2
- import globalThis from './global.js';
1
+ import { JOSEError, JWKSTimeout } from '../util/errors.js';
2
+ import globalThis, { isCloudflareWorkers } from './global.js';
3
3
  const fetchJwks = async (url, timeout) => {
4
4
  let controller;
5
+ let id;
6
+ let timedOut = false;
5
7
  if (typeof AbortController === 'function') {
6
8
  controller = new AbortController();
7
- setTimeout(() => controller.abort(), timeout);
9
+ id = setTimeout(() => {
10
+ timedOut = true;
11
+ controller.abort();
12
+ }, timeout);
8
13
  }
9
- const response = await globalThis.fetch(url.href, {
14
+ const response = await globalThis
15
+ .fetch(url.href, {
10
16
  signal: controller ? controller.signal : undefined,
11
17
  redirect: 'manual',
12
18
  method: 'GET',
13
- ...(globalThis.WebSocketPair === undefined
19
+ ...(!isCloudflareWorkers()
14
20
  ? {
15
21
  referrerPolicy: 'no-referrer',
16
22
  credentials: 'omit',
17
23
  mode: 'cors',
18
24
  }
19
25
  : undefined),
26
+ })
27
+ .catch((err) => {
28
+ if (timedOut)
29
+ throw new JWKSTimeout();
30
+ throw err;
20
31
  });
32
+ if (id !== undefined)
33
+ clearTimeout(id);
21
34
  if (response.status !== 200) {
22
35
  throw new JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response');
23
36
  }
@@ -0,0 +1,5 @@
1
+ import { isCryptoKey } from './webcrypto.js';
2
+ export default (key) => {
3
+ return isCryptoKey(key);
4
+ };
5
+ export const types = ['CryptoKey'];
@@ -1,11 +1,10 @@
1
1
  export class JOSEError extends Error {
2
2
  constructor(message) {
3
+ var _a;
3
4
  super(message);
4
5
  this.code = JOSEError.code;
5
6
  this.name = this.constructor.name;
6
- if (Error.captureStackTrace) {
7
- Error.captureStackTrace(this, this.constructor);
8
- }
7
+ (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor);
9
8
  }
10
9
  }
11
10
  JOSEError.code = 'ERR_JOSE_GENERIC';
@@ -91,6 +90,14 @@ export class JWKSMultipleMatchingKeys extends JOSEError {
91
90
  }
92
91
  }
93
92
  JWKSMultipleMatchingKeys.code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';
93
+ export class JWKSTimeout extends JOSEError {
94
+ constructor() {
95
+ super(...arguments);
96
+ this.code = JWKSTimeout.code;
97
+ this.message = 'request timed out';
98
+ }
99
+ }
100
+ JWKSTimeout.code = 'ERR_JWKS_TIMEOUT';
94
101
  export class JWSSignatureVerificationFailed extends JOSEError {
95
102
  constructor() {
96
103
  super(...arguments);
@@ -22,7 +22,11 @@ async function compactDecrypt(jwe, key, options) {
22
22
  tag: (tag || undefined),
23
23
  encrypted_key: encryptedKey || undefined,
24
24
  }, key, options);
25
- return { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader };
25
+ const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader };
26
+ if (typeof key === 'function') {
27
+ return { ...result, key: decrypted.key };
28
+ }
29
+ return result;
26
30
  }
27
31
  exports.compactDecrypt = compactDecrypt;
28
32
  exports.default = compactDecrypt;
@@ -95,8 +95,10 @@ async function flattenedDecrypt(jwe, key, options) {
95
95
  if (jwe.encrypted_key !== undefined) {
96
96
  encryptedKey = (0, base64url_js_1.decode)(jwe.encrypted_key);
97
97
  }
98
+ let resolvedKey = false;
98
99
  if (typeof key === 'function') {
99
100
  key = await key(parsedProt, jwe);
101
+ resolvedKey = true;
100
102
  }
101
103
  let cek;
102
104
  try {
@@ -135,6 +137,9 @@ async function flattenedDecrypt(jwe, key, options) {
135
137
  if (jwe.header !== undefined) {
136
138
  result.unprotectedHeader = jwe.header;
137
139
  }
140
+ if (resolvedKey) {
141
+ return { ...result, key };
142
+ }
138
143
  return result;
139
144
  }
140
145
  exports.flattenedDecrypt = flattenedDecrypt;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EmbeddedJWK = void 0;
4
- const parse_js_1 = require("./parse.js");
4
+ const import_js_1 = require("../key/import.js");
5
5
  const is_object_js_1 = require("../lib/is_object.js");
6
6
  const errors_js_1 = require("../util/errors.js");
7
7
  async function EmbeddedJWK(protectedHeader, token) {
@@ -12,8 +12,8 @@ async function EmbeddedJWK(protectedHeader, token) {
12
12
  if (!(0, is_object_js_1.default)(joseHeader.jwk)) {
13
13
  throw new errors_js_1.JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object');
14
14
  }
15
- const key = await (0, parse_js_1.default)(joseHeader.jwk, joseHeader.alg, true);
16
- if (key.type !== 'public') {
15
+ const key = await (0, import_js_1.importJWK)({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true);
16
+ if (key instanceof Uint8Array || key.type !== 'public') {
17
17
  throw new errors_js_1.JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key');
18
18
  }
19
19
  return key;
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.fromKeyLike = void 0;
4
- const key_to_jwk_js_1 = require("../runtime/key_to_jwk.js");
4
+ const export_js_1 = require("../key/export.js");
5
5
  async function fromKeyLike(key) {
6
- return (0, key_to_jwk_js_1.default)(key);
6
+ return (0, export_js_1.exportJWK)(key);
7
7
  }
8
8
  exports.fromKeyLike = fromKeyLike;
9
9
  exports.default = fromKeyLike;
@@ -1,38 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseJwk = void 0;
4
- const base64url_js_1 = require("../runtime/base64url.js");
5
- const jwk_to_key_js_1 = require("../runtime/jwk_to_key.js");
6
- const errors_js_1 = require("../util/errors.js");
7
- const is_object_js_1 = require("../lib/is_object.js");
4
+ const import_js_1 = require("../key/import.js");
8
5
  async function parseJwk(jwk, alg, octAsKeyObject) {
9
- if (!(0, is_object_js_1.default)(jwk)) {
10
- throw new TypeError('JWK must be an object');
11
- }
12
- alg || (alg = jwk.alg);
13
- if (typeof alg !== 'string' || !alg) {
14
- throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
15
- }
16
- switch (jwk.kty) {
17
- case 'oct':
18
- if (typeof jwk.k !== 'string' || !jwk.k) {
19
- throw new TypeError('missing "k" (Key Value) Parameter value');
20
- }
21
- octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : (octAsKeyObject = jwk.ext !== true);
22
- if (octAsKeyObject) {
23
- return (0, jwk_to_key_js_1.default)({ ...jwk, alg, ext: false });
24
- }
25
- return (0, base64url_js_1.decode)(jwk.k);
26
- case 'RSA':
27
- if (jwk.oth !== undefined) {
28
- throw new errors_js_1.JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');
29
- }
30
- case 'EC':
31
- case 'OKP':
32
- return (0, jwk_to_key_js_1.default)({ ...jwk, alg });
33
- default:
34
- throw new errors_js_1.JOSENotSupported('Unsupported "kty" (Key Type) Parameter value');
35
- }
6
+ return (0, import_js_1.importJWK)(jwk, alg, octAsKeyObject);
36
7
  }
37
8
  exports.parseJwk = parseJwk;
38
9
  exports.default = parseJwk;
@@ -2,11 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createRemoteJWKSet = void 0;
4
4
  const fetch_jwks_js_1 = require("../runtime/fetch_jwks.js");
5
- const parse_js_1 = require("../jwk/parse.js");
5
+ const import_js_1 = require("../key/import.js");
6
6
  const errors_js_1 = require("../util/errors.js");
7
7
  const is_object_js_1 = require("../lib/is_object.js");
8
8
  function getKtyFromAlg(alg) {
9
- switch (alg.substr(0, 2)) {
9
+ switch (typeof alg === 'string' && alg.substr(0, 2)) {
10
10
  case 'RS':
11
11
  case 'PS':
12
12
  return 'RSA';
@@ -35,7 +35,7 @@ class RemoteJWKSet {
35
35
  typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 30000;
36
36
  }
37
37
  coolingDown() {
38
- if (typeof this._cooldownStarted === 'undefined') {
38
+ if (!this._cooldownStarted) {
39
39
  return false;
40
40
  }
41
41
  return Date.now() < this._cooldownStarted + this._cooldownDuration;
@@ -59,7 +59,7 @@ class RemoteJWKSet {
59
59
  candidate = jwk.key_ops.includes('verify');
60
60
  }
61
61
  if (candidate && protectedHeader.alg === 'EdDSA') {
62
- candidate = ['Ed25519', 'Ed448'].includes(jwk.crv);
62
+ candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448';
63
63
  }
64
64
  if (candidate) {
65
65
  switch (protectedHeader.alg) {
@@ -91,13 +91,10 @@ class RemoteJWKSet {
91
91
  else if (length !== 1) {
92
92
  throw new errors_js_1.JWKSMultipleMatchingKeys();
93
93
  }
94
- if (!this._cached.has(jwk)) {
95
- this._cached.set(jwk, {});
96
- }
97
- const cached = this._cached.get(jwk);
94
+ const cached = this._cached.get(jwk) || this._cached.set(jwk, {}).get(jwk);
98
95
  if (cached[protectedHeader.alg] === undefined) {
99
- const keyObject = await (0, parse_js_1.default)({ ...jwk, alg: protectedHeader.alg });
100
- if (keyObject.type !== 'public') {
96
+ const keyObject = await (0, import_js_1.importJWK)({ ...jwk, ext: true }, protectedHeader.alg);
97
+ if (keyObject instanceof Uint8Array || keyObject.type !== 'public') {
101
98
  throw new errors_js_1.JWKSInvalid('JSON Web Key Set members must be public keys');
102
99
  }
103
100
  cached[protectedHeader.alg] = keyObject;
@@ -20,7 +20,11 @@ async function compactVerify(jws, key, options) {
20
20
  protected: protectedHeader || undefined,
21
21
  signature: (signature || undefined),
22
22
  }, key, options);
23
- return { payload: verified.payload, protectedHeader: verified.protectedHeader };
23
+ const result = { payload: verified.payload, protectedHeader: verified.protectedHeader };
24
+ if (typeof key === 'function') {
25
+ return { ...result, key: verified.key };
26
+ }
27
+ return result;
24
28
  }
25
29
  exports.compactVerify = compactVerify;
26
30
  exports.default = compactVerify;
@@ -73,8 +73,10 @@ async function flattenedVerify(jws, key, options) {
73
73
  else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) {
74
74
  throw new errors_js_1.JWSInvalid('JWS Payload must be a string or an Uint8Array instance');
75
75
  }
76
+ let resolvedKey = false;
76
77
  if (typeof key === 'function') {
77
78
  key = await key(parsedProt, jws);
79
+ resolvedKey = true;
78
80
  }
79
81
  (0, check_key_type_js_1.default)(alg, key, 'verify');
80
82
  const data = (0, buffer_utils_js_1.concat)(buffer_utils_js_1.encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ''), buffer_utils_js_1.encoder.encode('.'), typeof jws.payload === 'string' ? buffer_utils_js_1.encoder.encode(jws.payload) : jws.payload);
@@ -100,6 +102,9 @@ async function flattenedVerify(jws, key, options) {
100
102
  if (jws.header !== undefined) {
101
103
  result.unprotectedHeader = jws.header;
102
104
  }
105
+ if (resolvedKey) {
106
+ return { ...result, key };
107
+ }
103
108
  return result;
104
109
  }
105
110
  exports.flattenedVerify = flattenedVerify;
@@ -18,7 +18,11 @@ async function jwtDecrypt(jwt, key, options) {
18
18
  JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud)) {
19
19
  throw new errors_js_1.JWTClaimValidationFailed('replicated "aud" claim header parameter mismatch', 'aud', 'mismatch');
20
20
  }
21
- return { payload, protectedHeader };
21
+ const result = { payload, protectedHeader };
22
+ if (typeof key === 'function') {
23
+ return { ...result, key: decrypted.key };
24
+ }
25
+ return result;
22
26
  }
23
27
  exports.jwtDecrypt = jwtDecrypt;
24
28
  exports.default = jwtDecrypt;
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EncryptJWT = void 0;
4
4
  const encrypt_js_1 = require("../jwe/compact/encrypt.js");
5
5
  const buffer_utils_js_1 = require("../lib/buffer_utils.js");
6
- const jwt_producer_js_1 = require("../lib/jwt_producer.js");
7
- class EncryptJWT extends jwt_producer_js_1.default {
6
+ const produce_js_1 = require("./produce.js");
7
+ class EncryptJWT extends produce_js_1.ProduceJWT {
8
8
  setProtectedHeader(protectedHeader) {
9
9
  if (this._protectedHeader) {
10
10
  throw new TypeError('setProtectedHeader can only be called once');
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const epoch_js_1 = require("./epoch.js");
4
- const is_object_js_1 = require("./is_object.js");
5
- const secs_js_1 = require("./secs.js");
3
+ exports.ProduceJWT = void 0;
4
+ const epoch_js_1 = require("../lib/epoch.js");
5
+ const is_object_js_1 = require("../lib/is_object.js");
6
+ const secs_js_1 = require("../lib/secs.js");
6
7
  class ProduceJWT {
7
8
  constructor(payload) {
8
9
  if (!(0, is_object_js_1.default)(payload)) {
@@ -54,4 +55,4 @@ class ProduceJWT {
54
55
  return this;
55
56
  }
56
57
  }
57
- exports.default = ProduceJWT;
58
+ exports.ProduceJWT = ProduceJWT;
@@ -4,8 +4,8 @@ exports.SignJWT = void 0;
4
4
  const sign_js_1 = require("../jws/compact/sign.js");
5
5
  const errors_js_1 = require("../util/errors.js");
6
6
  const buffer_utils_js_1 = require("../lib/buffer_utils.js");
7
- const jwt_producer_js_1 = require("../lib/jwt_producer.js");
8
- class SignJWT extends jwt_producer_js_1.default {
7
+ const produce_js_1 = require("./produce.js");
8
+ class SignJWT extends produce_js_1.ProduceJWT {
9
9
  setProtectedHeader(protectedHeader) {
10
10
  this._protectedHeader = protectedHeader;
11
11
  return this;
@@ -5,8 +5,8 @@ const base64url = require("../runtime/base64url.js");
5
5
  const buffer_utils_js_1 = require("../lib/buffer_utils.js");
6
6
  const errors_js_1 = require("../util/errors.js");
7
7
  const jwt_claims_set_js_1 = require("../lib/jwt_claims_set.js");
8
- const jwt_producer_js_1 = require("../lib/jwt_producer.js");
9
- class UnsecuredJWT extends jwt_producer_js_1.default {
8
+ const produce_js_1 = require("./produce.js");
9
+ class UnsecuredJWT extends produce_js_1.ProduceJWT {
10
10
  encode() {
11
11
  const header = base64url.encode(JSON.stringify({ alg: 'none' }));
12
12
  const payload = base64url.encode(JSON.stringify(this._payload));
@@ -11,7 +11,11 @@ async function jwtVerify(jwt, key, options) {
11
11
  throw new errors_js_1.JWTInvalid('JWTs MUST NOT use unencoded payload');
12
12
  }
13
13
  const payload = (0, jwt_claims_set_js_1.default)(verified.protectedHeader, verified.payload, options);
14
- return { payload, protectedHeader: verified.protectedHeader };
14
+ const result = { payload, protectedHeader: verified.protectedHeader };
15
+ if (typeof key === 'function') {
16
+ return { ...result, key: verified.key };
17
+ }
18
+ return result;
15
19
  }
16
20
  exports.jwtVerify = jwtVerify;
17
21
  exports.default = jwtVerify;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.exportJWK = exports.exportPKCS8 = exports.exportSPKI = void 0;
4
+ const asn1_js_1 = require("../runtime/asn1.js");
5
+ const asn1_js_2 = require("../runtime/asn1.js");
6
+ const key_to_jwk_js_1 = require("../runtime/key_to_jwk.js");
7
+ async function exportSPKI(key) {
8
+ return (0, asn1_js_1.toSPKI)(key);
9
+ }
10
+ exports.exportSPKI = exportSPKI;
11
+ async function exportPKCS8(key) {
12
+ return (0, asn1_js_2.toPKCS8)(key);
13
+ }
14
+ exports.exportPKCS8 = exportPKCS8;
15
+ async function exportJWK(key) {
16
+ return (0, key_to_jwk_js_1.default)(key);
17
+ }
18
+ exports.exportJWK = exportJWK;
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.importJWK = exports.importPKCS8 = exports.importX509 = exports.importSPKI = void 0;
4
+ const base64url_js_1 = require("../runtime/base64url.js");
5
+ const asn1_js_1 = require("../runtime/asn1.js");
6
+ const asn1_js_2 = require("../runtime/asn1.js");
7
+ const jwk_to_key_js_1 = require("../runtime/jwk_to_key.js");
8
+ const errors_js_1 = require("../util/errors.js");
9
+ const format_pem_js_1 = require("../lib/format_pem.js");
10
+ const is_object_js_1 = require("../lib/is_object.js");
11
+ function getElement(seq) {
12
+ let result = [];
13
+ let next = 0;
14
+ while (next < seq.length) {
15
+ let nextPart = parseElement(seq.subarray(next));
16
+ result.push(nextPart);
17
+ next += nextPart.byteLength;
18
+ }
19
+ return result;
20
+ }
21
+ function parseElement(bytes) {
22
+ let position = 0;
23
+ let tag = bytes[0] & 0x1f;
24
+ position++;
25
+ if (tag === 0x1f) {
26
+ tag = 0;
27
+ while (bytes[position] >= 0x80) {
28
+ tag = tag * 128 + bytes[position] - 0x80;
29
+ position++;
30
+ }
31
+ tag = tag * 128 + bytes[position] - 0x80;
32
+ position++;
33
+ }
34
+ let length = 0;
35
+ if (bytes[position] < 0x80) {
36
+ length = bytes[position];
37
+ position++;
38
+ }
39
+ else {
40
+ let numberOfDigits = bytes[position] & 0x7f;
41
+ position++;
42
+ length = 0;
43
+ for (let i = 0; i < numberOfDigits; i++) {
44
+ length = length * 256 + bytes[position];
45
+ position++;
46
+ }
47
+ }
48
+ if (length === 0x80) {
49
+ length = 0;
50
+ while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) {
51
+ length++;
52
+ }
53
+ const byteLength = position + length + 2;
54
+ return {
55
+ byteLength,
56
+ contents: bytes.subarray(position, position + length),
57
+ raw: bytes.subarray(0, byteLength),
58
+ };
59
+ }
60
+ const byteLength = position + length;
61
+ return {
62
+ byteLength,
63
+ contents: bytes.subarray(position, byteLength),
64
+ raw: bytes.subarray(0, byteLength),
65
+ };
66
+ }
67
+ function spkiFromX509(buf) {
68
+ return (0, base64url_js_1.encodeBase64)(getElement(getElement(parseElement(buf).contents)[0].contents)[6].raw);
69
+ }
70
+ function getSPKI(x509) {
71
+ const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, '');
72
+ const raw = (0, base64url_js_1.decodeBase64)(pem);
73
+ return (0, format_pem_js_1.default)(spkiFromX509(raw), 'PUBLIC KEY');
74
+ }
75
+ async function importSPKI(spki, alg, options) {
76
+ if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) {
77
+ throw new TypeError('"spki" must be SPKI formatted string');
78
+ }
79
+ return (0, asn1_js_1.fromSPKI)(spki, alg, options);
80
+ }
81
+ exports.importSPKI = importSPKI;
82
+ async function importX509(x509, alg, options) {
83
+ if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) {
84
+ throw new TypeError('"x509" must be X.509 formatted string');
85
+ }
86
+ const spki = getSPKI(x509);
87
+ return (0, asn1_js_1.fromSPKI)(spki, alg, options);
88
+ }
89
+ exports.importX509 = importX509;
90
+ async function importPKCS8(pkcs8, alg, options) {
91
+ if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) {
92
+ throw new TypeError('"pkcs8" must be PCKS8 formatted string');
93
+ }
94
+ return (0, asn1_js_2.fromPKCS8)(pkcs8, alg, options);
95
+ }
96
+ exports.importPKCS8 = importPKCS8;
97
+ async function importJWK(jwk, alg, octAsKeyObject) {
98
+ if (!(0, is_object_js_1.default)(jwk)) {
99
+ throw new TypeError('JWK must be an object');
100
+ }
101
+ alg || (alg = jwk.alg);
102
+ if (typeof alg !== 'string' || !alg) {
103
+ throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
104
+ }
105
+ switch (jwk.kty) {
106
+ case 'oct':
107
+ if (typeof jwk.k !== 'string' || !jwk.k) {
108
+ throw new TypeError('missing "k" (Key Value) Parameter value');
109
+ }
110
+ octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : (octAsKeyObject = jwk.ext !== true);
111
+ if (octAsKeyObject) {
112
+ return (0, jwk_to_key_js_1.default)({ ...jwk, alg, ext: false });
113
+ }
114
+ return (0, base64url_js_1.decode)(jwk.k);
115
+ case 'RSA':
116
+ if (jwk.oth !== undefined) {
117
+ throw new errors_js_1.JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');
118
+ }
119
+ case 'EC':
120
+ case 'OKP':
121
+ return (0, jwk_to_key_js_1.default)({ ...jwk, alg });
122
+ default:
123
+ throw new errors_js_1.JOSENotSupported('Unsupported "kty" (Key Type) Parameter value');
124
+ }
125
+ }
126
+ exports.importJWK = importJWK;