jose 6.2.6 → 6.2.8

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 (36) hide show
  1. package/dist/webapi/jwe/compact/decrypt.js +2 -2
  2. package/dist/webapi/jwe/flattened/encrypt.js +12 -12
  3. package/dist/webapi/jwe/general/decrypt.js +8 -0
  4. package/dist/webapi/jwe/general/encrypt.js +51 -52
  5. package/dist/webapi/jwks/local.js +13 -34
  6. package/dist/webapi/jwks/remote.js +17 -26
  7. package/dist/webapi/jws/compact/verify.js +2 -2
  8. package/dist/webapi/jws/flattened/sign.js +1 -9
  9. package/dist/webapi/jws/general/sign.js +12 -21
  10. package/dist/webapi/jws/general/verify.js +13 -11
  11. package/dist/webapi/jwt/decrypt.js +3 -3
  12. package/dist/webapi/jwt/verify.js +4 -4
  13. package/dist/webapi/key/export.js +3 -3
  14. package/dist/webapi/key/generate_key_pair.js +10 -9
  15. package/dist/webapi/key/generate_secret.js +2 -2
  16. package/dist/webapi/lib/asn1.js +32 -65
  17. package/dist/webapi/lib/content_encryption.js +16 -34
  18. package/dist/webapi/lib/crypto_key.js +6 -0
  19. package/dist/webapi/lib/invalid_key_input.js +0 -1
  20. package/dist/webapi/lib/jwe_algorithms.js +48 -84
  21. package/dist/webapi/lib/jwe_decrypt.js +46 -41
  22. package/dist/webapi/lib/jwe_encrypt.js +14 -13
  23. package/dist/webapi/lib/jwk_to_key.js +5 -10
  24. package/dist/webapi/lib/jws_algorithms.js +22 -23
  25. package/dist/webapi/lib/jws_sign.js +12 -6
  26. package/dist/webapi/lib/jws_verify.js +26 -27
  27. package/dist/webapi/lib/jwt_claims_set.js +60 -102
  28. package/dist/webapi/lib/key.js +61 -99
  29. package/dist/webapi/lib/key_algorithm.js +7 -13
  30. package/dist/webapi/lib/key_descriptor.js +1 -1
  31. package/dist/webapi/lib/key_management.js +74 -161
  32. package/dist/webapi/lib/options.js +11 -14
  33. package/dist/webapi/lib/signing.js +6 -16
  34. package/dist/webapi/lib/type_checks.js +13 -18
  35. package/dist/webapi/util/base64url.js +4 -3
  36. package/package.json +1 -1
@@ -6,75 +6,38 @@ import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
6
6
  import { decodeBase64url, digest } from './helpers.js';
7
7
  import { generateCek, encrypt, decrypt } from './content_encryption.js';
8
8
  import { isObject } from './type_checks.js';
9
- import { checkCryptoKey, checkUsage } from './crypto_key.js';
10
- import { checkModulusLength } from './signing.js';
9
+ import { checkCryptoKey, checkModulusLength, checkUsage } from './crypto_key.js';
11
10
  import { concat, encode, uint32be } from './buffer_utils.js';
12
11
  import { assertCryptoKey } from './is_key_like.js';
13
12
  function checkEcdhCryptoKey(key, usage) {
14
- switch (key.algorithm.name) {
15
- case 'ECDH':
16
- case 'X25519':
17
- break;
18
- default:
19
- throw new TypeError('CryptoKey does not support this operation, its algorithm.name must be ECDH or X25519');
13
+ if (key.algorithm.name !== 'ECDH' && key.algorithm.name !== 'X25519') {
14
+ throw new TypeError('CryptoKey does not support this operation, its algorithm.name must be ECDH or X25519');
20
15
  }
21
16
  checkUsage(key, usage);
22
17
  }
23
- function checkKeySize(key, alg) {
24
- if (key.algorithm.length !== parseInt(alg.slice(1, 4), 10)) {
25
- throw new TypeError(`Invalid key size for alg: ${alg}`);
26
- }
27
- }
28
- function aeskwCryptoKey(key, alg, usage) {
29
- if (key instanceof Uint8Array) {
30
- return crypto.subtle.importKey('raw', key, 'AES-KW', true, [usage]);
31
- }
32
- checkCryptoKey(key, jweAlgorithm(alg).subtle, usage);
33
- return key;
18
+ async function aeskwCryptoKey(key, alg, usage) {
19
+ const expected = jweAlgorithm(alg).subtle;
20
+ const cryptoKey = key instanceof Uint8Array
21
+ ? await crypto.subtle.importKey('raw', key, 'AES-KW', true, [
22
+ usage,
23
+ ])
24
+ : key;
25
+ checkCryptoKey(cryptoKey, expected, usage);
26
+ return cryptoKey;
34
27
  }
35
28
  async function aeskwWrap(alg, key, cek) {
36
29
  const cryptoKey = await aeskwCryptoKey(key, alg, 'wrapKey');
37
- checkKeySize(cryptoKey, alg);
38
30
  const cryptoKeyCek = await crypto.subtle.importKey('raw', cek, { hash: 'SHA-256', name: 'HMAC' }, true, ['sign']);
39
31
  return new Uint8Array(await crypto.subtle.wrapKey('raw', cryptoKeyCek, cryptoKey, 'AES-KW'));
40
32
  }
41
33
  async function aeskwUnwrap(alg, key, encryptedKey) {
42
34
  const cryptoKey = await aeskwCryptoKey(key, alg, 'unwrapKey');
43
- checkKeySize(cryptoKey, alg);
44
35
  const cryptoKeyCek = await crypto.subtle.unwrapKey('raw', encryptedKey, cryptoKey, 'AES-KW', { hash: 'SHA-256', name: 'HMAC' }, true, ['sign']);
45
36
  return new Uint8Array(await crypto.subtle.exportKey('raw', cryptoKeyCek));
46
37
  }
47
- async function aesGcmKwWrap(gcm, key, cek, iv) {
48
- const wrapped = await encrypt(gcm, cek, key, iv, new Uint8Array());
49
- return {
50
- encryptedKey: wrapped.ciphertext,
51
- iv: b64u(wrapped.iv),
52
- tag: b64u(wrapped.tag),
53
- };
54
- }
55
- async function aesGcmKwUnwrap(gcm, key, encryptedKey, iv, tag) {
56
- return decrypt(gcm, key, encryptedKey, iv, tag, new Uint8Array());
57
- }
58
- const subtleAlgorithm = (alg) => {
59
- switch (alg) {
60
- case 'RSA-OAEP':
61
- case 'RSA-OAEP-256':
62
- case 'RSA-OAEP-384':
63
- case 'RSA-OAEP-512':
64
- return 'RSA-OAEP';
65
- default:
66
- throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
67
- }
68
- };
69
- async function rsaesEncrypt(alg, key, cek) {
70
- checkCryptoKey(key, jweAlgorithm(alg).subtle, 'encrypt');
71
- checkModulusLength(alg, key);
72
- return new Uint8Array(await crypto.subtle.encrypt(subtleAlgorithm(alg), key, cek));
73
- }
74
- async function rsaesDecrypt(alg, key, encryptedKey) {
75
- checkCryptoKey(key, jweAlgorithm(alg).subtle, 'decrypt');
38
+ function checkRsaKey(alg, key, usage) {
39
+ checkCryptoKey(key, jweAlgorithm(alg).subtle, usage);
76
40
  checkModulusLength(alg, key);
77
- return new Uint8Array(await crypto.subtle.decrypt(subtleAlgorithm(alg), key, encryptedKey));
78
41
  }
79
42
  function pbes2CryptoKey(key, alg) {
80
43
  if (key instanceof Uint8Array) {
@@ -85,7 +48,6 @@ function pbes2CryptoKey(key, alg) {
85
48
  checkCryptoKey(key, jweAlgorithm(alg).subtle, 'deriveBits');
86
49
  return key;
87
50
  }
88
- const concatSalt = (alg, p2sInput) => concat(encode(alg), Uint8Array.of(0x00), p2sInput);
89
51
  async function deriveKey(p2s, alg, p2c, key) {
90
52
  if (!(p2s instanceof Uint8Array) || p2s.length < 8) {
91
53
  throw new JWEInvalid('PBES2 Salt Input must be 8 or more octets');
@@ -93,7 +55,7 @@ async function deriveKey(p2s, alg, p2c, key) {
93
55
  if (!Number.isSafeInteger(p2c) || Math.sign(p2c) !== 1) {
94
56
  throw new JWEInvalid('PBES2 Count Input must be a positive integer');
95
57
  }
96
- const salt = concatSalt(alg, p2s);
58
+ const salt = concat(encode(alg), Uint8Array.of(0), p2s);
97
59
  const keylen = parseInt(alg.slice(13, 16), 10);
98
60
  const subtleAlg = {
99
61
  hash: `SHA-${alg.slice(8, 11)}`,
@@ -104,15 +66,6 @@ async function deriveKey(p2s, alg, p2c, key) {
104
66
  const cryptoKey = await pbes2CryptoKey(key, alg);
105
67
  return new Uint8Array(await crypto.subtle.deriveBits(subtleAlg, cryptoKey, keylen));
106
68
  }
107
- async function pbes2kwWrap(alg, key, cek, p2c = 2048, p2s = crypto.getRandomValues(new Uint8Array(16))) {
108
- const derived = await deriveKey(p2s, alg, p2c, key);
109
- const encryptedKey = await aeskwWrap(alg.slice(-6), derived, cek);
110
- return { encryptedKey, p2c, p2s: b64u(p2s) };
111
- }
112
- async function pbes2kwUnwrap(alg, key, encryptedKey, p2c, p2s) {
113
- const derived = await deriveKey(p2s, alg, p2c, key);
114
- return aeskwUnwrap(alg.slice(-6), derived, encryptedKey);
115
- }
116
69
  function lengthAndInput(input) {
117
70
  return concat(uint32be(input.length), input);
118
71
  }
@@ -122,11 +75,7 @@ async function concatKdf(Z, L, OtherInfo) {
122
75
  const reps = Math.ceil(dkLen / hashLen);
123
76
  const dk = new Uint8Array(reps * hashLen);
124
77
  for (let i = 1; i <= reps; i++) {
125
- const hashInput = new Uint8Array(4 + Z.length + OtherInfo.length);
126
- hashInput.set(uint32be(i), 0);
127
- hashInput.set(Z, 4);
128
- hashInput.set(OtherInfo, 4 + Z.length);
129
- const hashResult = await digest('sha256', hashInput);
78
+ const hashResult = await digest('sha256', concat(uint32be(i), Z, OtherInfo));
130
79
  dk.set(hashResult, (i - 1) * hashLen);
131
80
  }
132
81
  return dk.slice(0, dkLen);
@@ -134,58 +83,47 @@ async function concatKdf(Z, L, OtherInfo) {
134
83
  async function ecdhesDeriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(), apv = new Uint8Array()) {
135
84
  checkEcdhCryptoKey(publicKey);
136
85
  checkEcdhCryptoKey(privateKey, 'deriveBits');
137
- const algorithmID = lengthAndInput(encode(algorithm));
138
- const partyUInfo = lengthAndInput(apu);
139
- const partyVInfo = lengthAndInput(apv);
140
- const suppPubInfo = uint32be(keyLength);
141
- const suppPrivInfo = new Uint8Array();
142
- const otherInfo = concat(algorithmID, partyUInfo, partyVInfo, suppPubInfo, suppPrivInfo);
86
+ const otherInfo = concat(lengthAndInput(encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength));
143
87
  const Z = new Uint8Array(await crypto.subtle.deriveBits({
144
88
  name: publicKey.algorithm.name,
145
89
  public: publicKey,
146
- }, privateKey, getEcdhBitLength(publicKey)));
90
+ }, privateKey, publicKey.algorithm.name === 'X25519'
91
+ ? 256
92
+ : Math.ceil(parseInt(publicKey.algorithm.namedCurve.slice(-3), 10) / 8) << 3));
147
93
  return concatKdf(Z, keyLength, otherInfo);
148
94
  }
149
- function getEcdhBitLength(publicKey) {
150
- if (publicKey.algorithm.name === 'X25519') {
151
- return 256;
152
- }
153
- return (Math.ceil(parseInt(publicKey.algorithm.namedCurve.slice(-3), 10) / 8) << 3);
154
- }
155
- function ecdhesAllowed(key) {
156
- switch (key.algorithm.namedCurve) {
157
- case 'P-256':
158
- case 'P-384':
159
- case 'P-521':
160
- return true;
161
- default:
162
- return key.algorithm.name === 'X25519';
95
+ function assertEcdhKey(key) {
96
+ assertCryptoKey(key);
97
+ const curve = key.algorithm.namedCurve;
98
+ if (curve !== 'P-256' &&
99
+ curve !== 'P-384' &&
100
+ curve !== 'P-521' &&
101
+ key.algorithm.name !== 'X25519') {
102
+ throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
163
103
  }
164
104
  }
165
- const unsupportedAlgHeader = 'Invalid or unsupported "alg" (JWE Algorithm) header value';
166
105
  function assertEncryptedKey(encryptedKey) {
167
106
  if (encryptedKey === undefined)
168
107
  throw new JWEInvalid('JWE Encrypted Key missing');
169
108
  }
109
+ function assertNoEncryptedKey(encryptedKey) {
110
+ if (encryptedKey !== undefined)
111
+ throw new JWEInvalid('Encountered unexpected JWE Encrypted Key');
112
+ }
170
113
  export async function decryptKeyManagement(alg, enc, key, encryptedKey, joseHeader, options) {
171
- switch (alg) {
172
- case 'dir': {
173
- if (encryptedKey !== undefined)
174
- throw new JWEInvalid('Encountered unexpected JWE Encrypted Key');
175
- return key;
176
- }
177
- case 'ECDH-ES':
178
- if (encryptedKey !== undefined)
179
- throw new JWEInvalid('Encountered unexpected JWE Encrypted Key');
180
- case 'ECDH-ES+A128KW':
181
- case 'ECDH-ES+A192KW':
182
- case 'ECDH-ES+A256KW': {
114
+ const entry = jweAlgorithm(alg);
115
+ if (alg === 'dir') {
116
+ assertNoEncryptedKey(encryptedKey);
117
+ return key;
118
+ }
119
+ switch (entry.subtle.name) {
120
+ case 'ECDH': {
121
+ if (alg === 'ECDH-ES')
122
+ assertNoEncryptedKey(encryptedKey);
183
123
  if (!isObject(joseHeader.epk))
184
124
  throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`);
185
- assertCryptoKey(key);
186
- if (!ecdhesAllowed(key))
187
- throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
188
- const epk = await jwkToKey(jweAlgorithm(alg), joseHeader.epk);
125
+ assertEcdhKey(key);
126
+ const epk = await jwkToKey(entry, joseHeader.epk);
189
127
  let partyUInfo;
190
128
  let partyVInfo;
191
129
  if (joseHeader.apu !== undefined) {
@@ -204,17 +142,13 @@ export async function decryptKeyManagement(alg, enc, key, encryptedKey, joseHead
204
142
  assertEncryptedKey(encryptedKey);
205
143
  return aeskwUnwrap(alg.slice(-6), sharedSecret, encryptedKey);
206
144
  }
207
- case 'RSA-OAEP':
208
- case 'RSA-OAEP-256':
209
- case 'RSA-OAEP-384':
210
- case 'RSA-OAEP-512': {
145
+ case 'RSA-OAEP': {
211
146
  assertEncryptedKey(encryptedKey);
212
147
  assertCryptoKey(key);
213
- return rsaesDecrypt(alg, key, encryptedKey);
148
+ checkRsaKey(alg, key, 'decrypt');
149
+ return new Uint8Array(await crypto.subtle.decrypt('RSA-OAEP', key, encryptedKey));
214
150
  }
215
- case 'PBES2-HS256+A128KW':
216
- case 'PBES2-HS384+A192KW':
217
- case 'PBES2-HS512+A256KW': {
151
+ case 'PBKDF2': {
218
152
  assertEncryptedKey(encryptedKey);
219
153
  if (typeof joseHeader.p2c !== 'number')
220
154
  throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`);
@@ -223,19 +157,15 @@ export async function decryptKeyManagement(alg, enc, key, encryptedKey, joseHead
223
157
  throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`);
224
158
  if (typeof joseHeader.p2s !== 'string')
225
159
  throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`);
226
- let p2s;
227
- p2s = decodeBase64url(joseHeader.p2s, 'p2s', JWEInvalid);
228
- return pbes2kwUnwrap(alg, key, encryptedKey, joseHeader.p2c, p2s);
160
+ const p2s = decodeBase64url(joseHeader.p2s, 'p2s', JWEInvalid);
161
+ const derived = await deriveKey(p2s, alg, joseHeader.p2c, key);
162
+ return aeskwUnwrap(alg.slice(-6), derived, encryptedKey);
229
163
  }
230
- case 'A128KW':
231
- case 'A192KW':
232
- case 'A256KW': {
164
+ case 'AES-KW': {
233
165
  assertEncryptedKey(encryptedKey);
234
166
  return aeskwUnwrap(alg, key, encryptedKey);
235
167
  }
236
- case 'A128GCMKW':
237
- case 'A192GCMKW':
238
- case 'A256GCMKW': {
168
+ case 'AES-GCM': {
239
169
  assertEncryptedKey(encryptedKey);
240
170
  if (typeof joseHeader.iv !== 'string')
241
171
  throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`);
@@ -245,10 +175,7 @@ export async function decryptKeyManagement(alg, enc, key, encryptedKey, joseHead
245
175
  iv = decodeBase64url(joseHeader.iv, 'iv', JWEInvalid);
246
176
  let tag;
247
177
  tag = decodeBase64url(joseHeader.tag, 'tag', JWEInvalid);
248
- return aesGcmKwUnwrap(jweEncryption(jweAlgorithm(alg).gcmkw), key, encryptedKey, iv, tag);
249
- }
250
- default: {
251
- throw new JOSENotSupported(unsupportedAlgHeader);
178
+ return decrypt(jweEncryption(alg.slice(0, -2)), key, encryptedKey, iv, tag, new Uint8Array());
252
179
  }
253
180
  }
254
181
  }
@@ -256,23 +183,16 @@ export async function encryptKeyManagement(alg, enc, key, providedCek, providedP
256
183
  let encryptedKey;
257
184
  let parameters;
258
185
  let cek;
259
- switch (alg) {
260
- case 'dir': {
261
- cek = key;
262
- break;
263
- }
264
- case 'ECDH-ES':
265
- case 'ECDH-ES+A128KW':
266
- case 'ECDH-ES+A192KW':
267
- case 'ECDH-ES+A256KW': {
268
- assertCryptoKey(key);
269
- if (!ecdhesAllowed(key)) {
270
- throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
271
- }
186
+ const entry = jweAlgorithm(alg);
187
+ if (alg === 'dir')
188
+ return [key, undefined, undefined];
189
+ switch (entry.subtle.name) {
190
+ case 'ECDH': {
191
+ assertEcdhKey(key);
272
192
  const { apu, apv } = providedParameters;
273
193
  let ephemeralKey;
274
194
  if (providedParameters.epk) {
275
- ephemeralKey = (await prepareKey(jweAlgorithm(alg), providedParameters.epk, 'decrypt'));
195
+ ephemeralKey = (await prepareKey(entry, providedParameters.epk, 'decrypt'));
276
196
  }
277
197
  else {
278
198
  ephemeralKey = (await crypto.subtle.generateKey(key.algorithm, true, ['deriveBits'])).privateKey;
@@ -303,41 +223,34 @@ export async function encryptKeyManagement(alg, enc, key, providedCek, providedP
303
223
  encryptedKey = await aeskwWrap(kwAlg, sharedSecret, cek);
304
224
  break;
305
225
  }
306
- case 'RSA-OAEP':
307
- case 'RSA-OAEP-256':
308
- case 'RSA-OAEP-384':
309
- case 'RSA-OAEP-512': {
226
+ case 'RSA-OAEP': {
310
227
  cek = providedCek || generateCek(enc);
311
228
  assertCryptoKey(key);
312
- encryptedKey = await rsaesEncrypt(alg, key, cek);
229
+ checkRsaKey(alg, key, 'encrypt');
230
+ encryptedKey = new Uint8Array(await crypto.subtle.encrypt('RSA-OAEP', key, cek));
313
231
  break;
314
232
  }
315
- case 'PBES2-HS256+A128KW':
316
- case 'PBES2-HS384+A192KW':
317
- case 'PBES2-HS512+A256KW': {
233
+ case 'PBKDF2': {
318
234
  cek = providedCek || generateCek(enc);
319
- const { p2c, p2s } = providedParameters;
320
- ({ encryptedKey, ...parameters } = await pbes2kwWrap(alg, key, cek, p2c, p2s));
235
+ const { p2c = 2048, p2s = crypto.getRandomValues(new Uint8Array(16)) } = providedParameters;
236
+ const derived = await deriveKey(p2s, alg, p2c, key);
237
+ encryptedKey = await aeskwWrap(alg.slice(-6), derived, cek);
238
+ parameters = { p2c, p2s: b64u(p2s) };
321
239
  break;
322
240
  }
323
- case 'A128KW':
324
- case 'A192KW':
325
- case 'A256KW': {
241
+ case 'AES-KW': {
326
242
  cek = providedCek || generateCek(enc);
327
243
  encryptedKey = await aeskwWrap(alg, key, cek);
328
244
  break;
329
245
  }
330
- case 'A128GCMKW':
331
- case 'A192GCMKW':
332
- case 'A256GCMKW': {
246
+ case 'AES-GCM': {
333
247
  cek = providedCek || generateCek(enc);
334
248
  const { iv } = providedParameters;
335
- ({ encryptedKey, ...parameters } = await aesGcmKwWrap(jweEncryption(jweAlgorithm(alg).gcmkw), key, cek, iv));
249
+ const wrapped = await encrypt(jweEncryption(alg.slice(0, -2)), cek, key, iv, new Uint8Array());
250
+ encryptedKey = wrapped.ciphertext;
251
+ parameters = { iv: b64u(wrapped.iv), tag: b64u(wrapped.tag) };
336
252
  break;
337
253
  }
338
- default: {
339
- throw new JOSENotSupported(unsupportedAlgHeader);
340
- }
341
254
  }
342
- return { cek, encryptedKey, parameters };
255
+ return [cek, encryptedKey, parameters];
343
256
  }
@@ -1,6 +1,6 @@
1
1
  import { JOSENotSupported, JWEInvalid, JWSInvalid } from '../util/errors.js';
2
- export const JWS_RECOGNIZED = new Map([['b64', true]]);
3
- export const JWE_RECOGNIZED = new Map();
2
+ export const JWS_RECOGNIZED = { __proto__: null, b64: true };
3
+ export const JWE_RECOGNIZED = { __proto__: null };
4
4
  export function validateAlgorithms(option, algorithms) {
5
5
  if (algorithms !== undefined &&
6
6
  (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) {
@@ -22,30 +22,27 @@ export function validateCrit(Err, recognizedDefault, recognizedOption, protected
22
22
  throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
23
23
  }
24
24
  if (!protectedHeader || protectedHeader.crit === undefined) {
25
- return new Set();
25
+ return [];
26
26
  }
27
27
  if (!Array.isArray(protectedHeader.crit) ||
28
28
  protectedHeader.crit.length === 0 ||
29
29
  protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) {
30
30
  throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');
31
31
  }
32
- let recognized;
33
- if (recognizedOption !== undefined) {
34
- recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]);
35
- }
36
- else {
37
- recognized = recognizedDefault;
38
- }
32
+ const recognized = recognizedOption === undefined
33
+ ? recognizedDefault
34
+ : { __proto__: null, ...recognizedOption, ...recognizedDefault };
39
35
  for (const parameter of protectedHeader.crit) {
40
- if (!recognized.has(parameter)) {
36
+ if (!(parameter in recognized)) {
41
37
  throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`);
42
38
  }
43
- if (joseHeader[parameter] === undefined) {
39
+ if (!Object.hasOwn(joseHeader, parameter) || joseHeader[parameter] === undefined) {
44
40
  throw new Err(`Extension Header Parameter "${parameter}" is missing`);
45
41
  }
46
- if (recognized.get(parameter) && protectedHeader[parameter] === undefined) {
42
+ if (recognized[parameter] &&
43
+ (!Object.hasOwn(protectedHeader, parameter) || protectedHeader[parameter] === undefined)) {
47
44
  throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`);
48
45
  }
49
46
  }
50
- return new Set(protectedHeader.crit);
47
+ return protectedHeader.crit;
51
48
  }
@@ -1,34 +1,24 @@
1
- import { checkCryptoKey } from './crypto_key.js';
2
- export function checkModulusLength(alg, key) {
3
- const { modulusLength } = key.algorithm;
4
- if (typeof modulusLength !== 'number' || modulusLength < 2048) {
5
- throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);
6
- }
7
- }
8
- function checkSigCryptoKey(entry, key, usage) {
9
- checkCryptoKey(key, entry.subtle, usage);
10
- if (entry.minModulusLength) {
11
- checkModulusLength(entry.alg, key);
12
- }
13
- }
1
+ import { checkCryptoKey, checkModulusLength } from './crypto_key.js';
14
2
  async function getSigKey(entry, key, usage) {
15
3
  if (key instanceof Uint8Array) {
16
4
  return crypto.subtle.importKey('raw', key, entry.subtle, false, [
17
5
  usage,
18
6
  ]);
19
7
  }
20
- checkSigCryptoKey(entry, key, usage);
8
+ checkCryptoKey(key, entry.subtle, usage);
9
+ if (entry.minRsaBits)
10
+ checkModulusLength(entry.alg, key);
21
11
  return key;
22
12
  }
23
13
  export async function sign(entry, key, data) {
24
14
  const cryptoKey = await getSigKey(entry, key, 'sign');
25
- const signature = await crypto.subtle.sign(entry.operation, cryptoKey, data);
15
+ const signature = await crypto.subtle.sign(entry.signing, cryptoKey, data);
26
16
  return new Uint8Array(signature);
27
17
  }
28
18
  export async function verify(entry, key, signature, data) {
29
19
  const cryptoKey = await getSigKey(entry, key, 'verify');
30
20
  try {
31
- return await crypto.subtle.verify(entry.operation, cryptoKey, signature, data);
21
+ return await crypto.subtle.verify(entry.signing, cryptoKey, signature, data);
32
22
  }
33
23
  catch {
34
24
  return false;
@@ -1,34 +1,29 @@
1
- const isObjectLike = (value) => typeof value === 'object' && value !== null;
2
1
  export function isObject(input) {
3
- if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') {
2
+ if (typeof input !== 'object' ||
3
+ input === null ||
4
+ Object.prototype.toString.call(input) !== '[object Object]') {
4
5
  return false;
5
6
  }
6
- if (Object.getPrototypeOf(input) === null) {
7
+ const prototype = Object.getPrototypeOf(input);
8
+ if (prototype === null) {
7
9
  return true;
8
10
  }
9
- let proto = input;
11
+ let proto = prototype;
10
12
  while (Object.getPrototypeOf(proto) !== null) {
11
13
  proto = Object.getPrototypeOf(proto);
12
14
  }
13
- return Object.getPrototypeOf(input) === proto;
15
+ return prototype === proto;
14
16
  }
15
17
  export function isDisjoint(...headers) {
16
- const sources = headers.filter(Boolean);
17
- if (sources.length === 0 || sources.length === 1) {
18
- return true;
19
- }
20
- let acc;
21
- for (const header of sources) {
22
- const parameters = Object.keys(header);
23
- if (!acc || acc.size === 0) {
24
- acc = new Set(parameters);
18
+ const parameters = new Set();
19
+ for (const header of headers) {
20
+ if (!header)
25
21
  continue;
26
- }
27
- for (const parameter of parameters) {
28
- if (acc.has(parameter)) {
22
+ for (const parameter of Object.keys(header)) {
23
+ if (parameters.has(parameter)) {
29
24
  return false;
30
25
  }
31
- acc.add(parameter);
26
+ parameters.add(parameter);
32
27
  }
33
28
  }
34
29
  return true;
@@ -1,5 +1,6 @@
1
1
  import { encoder, decoder } from '../lib/buffer_utils.js';
2
2
  import { encodeBase64, decodeBase64 } from '../lib/base64.js';
3
+ const invalid = 'The input to be decoded is not correctly encoded.';
3
4
  export function decode(input) {
4
5
  if (Uint8Array.fromBase64) {
5
6
  try {
@@ -8,7 +9,7 @@ export function decode(input) {
8
9
  });
9
10
  }
10
11
  catch (cause) {
11
- throw new TypeError('The input to be decoded is not correctly encoded.', { cause });
12
+ throw new TypeError(invalid, { cause });
12
13
  }
13
14
  }
14
15
  let encoded = input;
@@ -16,14 +17,14 @@ export function decode(input) {
16
17
  encoded = decoder.decode(encoded);
17
18
  }
18
19
  if (encoded.includes('+') || encoded.includes('/')) {
19
- throw new TypeError('The input to be decoded is not correctly encoded.');
20
+ throw new TypeError(invalid);
20
21
  }
21
22
  encoded = encoded.replace(/-/g, '+').replace(/_/g, '/');
22
23
  try {
23
24
  return decodeBase64(encoded);
24
25
  }
25
26
  catch {
26
- throw new TypeError('The input to be decoded is not correctly encoded.');
27
+ throw new TypeError(invalid);
27
28
  }
28
29
  }
29
30
  export function encode(input) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jose",
3
- "version": "6.2.6",
3
+ "version": "6.2.8",
4
4
  "description": "JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes",
5
5
  "keywords": [
6
6
  "akp",