@zuplo/cli 6.74.2 → 6.74.6

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 (64) hide show
  1. package/dist/cmds/test.d.ts.map +1 -1
  2. package/dist/cmds/test.js +8 -0
  3. package/dist/cmds/test.js.map +1 -1
  4. package/dist/common/utils/pnpm-lifecycle.d.ts.map +1 -1
  5. package/dist/common/utils/pnpm-lifecycle.js +1 -4
  6. package/dist/common/utils/pnpm-lifecycle.js.map +1 -1
  7. package/dist/common/utils/pnpm-lifecycle.test.js +23 -4
  8. package/dist/common/utils/pnpm-lifecycle.test.js.map +1 -1
  9. package/dist/test/handler.d.ts +2 -1
  10. package/dist/test/handler.d.ts.map +1 -1
  11. package/dist/test/handler.js.map +1 -1
  12. package/dist/test/invoke-test.d.ts +3 -2
  13. package/dist/test/invoke-test.d.ts.map +1 -1
  14. package/dist/test/invoke-test.js +26 -0
  15. package/dist/test/invoke-test.js.map +1 -1
  16. package/dist/test/invoke-test.test.js +16 -0
  17. package/dist/test/invoke-test.test.js.map +1 -1
  18. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwe/compact/decrypt.js +2 -2
  19. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwe/flattened/encrypt.js +12 -12
  20. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwe/general/encrypt.js +50 -51
  21. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwks/local.js +10 -31
  22. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwks/remote.js +17 -26
  23. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jws/compact/verify.js +2 -2
  24. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jws/flattened/sign.js +1 -9
  25. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jws/general/sign.js +12 -21
  26. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jws/general/verify.js +13 -11
  27. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwt/decrypt.js +3 -3
  28. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwt/verify.js +4 -4
  29. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/key/export.js +3 -3
  30. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/key/generate_key_pair.js +7 -6
  31. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/asn1.js +29 -62
  32. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/content_encryption.js +16 -34
  33. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/crypto_key.js +6 -0
  34. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/invalid_key_input.js +0 -1
  35. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwe_algorithms.js +44 -71
  36. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwe_decrypt.js +46 -41
  37. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwe_encrypt.js +14 -13
  38. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwk_to_key.js +5 -10
  39. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jws_algorithms.js +20 -18
  40. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jws_sign.js +12 -6
  41. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jws_verify.js +26 -27
  42. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +60 -102
  43. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/key.js +61 -99
  44. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/key_algorithm.js +2 -8
  45. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/key_descriptor.js +1 -1
  46. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/key_management.js +74 -161
  47. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/options.js +11 -14
  48. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/signing.js +6 -16
  49. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/type_checks.js +13 -18
  50. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/util/base64url.js +4 -3
  51. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/package.json +1 -1
  52. package/node_modules/@zuplo/core/package.json +1 -1
  53. package/node_modules/@zuplo/graphql/package.json +1 -1
  54. package/node_modules/@zuplo/openapi-tools/package.json +3 -3
  55. package/node_modules/@zuplo/otel/package.json +1 -1
  56. package/node_modules/@zuplo/runtime/out/esm/{chunk-B5LJC45G.js → chunk-CKGECOOJ.js} +88 -88
  57. package/node_modules/@zuplo/runtime/out/esm/chunk-CKGECOOJ.js.map +1 -0
  58. package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
  59. package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +1 -1
  60. package/node_modules/@zuplo/runtime/out/types/index.d.ts +5 -1
  61. package/node_modules/@zuplo/runtime/package.json +1 -1
  62. package/package.json +6 -6
  63. package/node_modules/@zuplo/runtime/out/esm/chunk-B5LJC45G.js.map +0 -1
  64. /package/node_modules/@zuplo/runtime/out/esm/{chunk-B5LJC45G.js.LEGAL.txt → chunk-CKGECOOJ.js.LEGAL.txt} +0 -0
@@ -7,17 +7,7 @@ const tag = (key) => key[Symbol.toStringTag];
7
7
  const jwkMatchesOp = (entry, key, usage) => {
8
8
  const { alg } = entry;
9
9
  if (key.use !== undefined) {
10
- let expected;
11
- switch (usage) {
12
- case 'sign':
13
- case 'verify':
14
- expected = 'sig';
15
- break;
16
- case 'encrypt':
17
- case 'decrypt':
18
- expected = 'enc';
19
- break;
20
- }
10
+ const expected = usage === 'sign' || usage === 'verify' ? 'sig' : 'enc';
21
11
  if (key.use !== expected) {
22
12
  throw new TypeError(`Invalid key for this operation, its "use" must be "${expected}" when present`);
23
13
  }
@@ -26,79 +16,56 @@ const jwkMatchesOp = (entry, key, usage) => {
26
16
  throw new TypeError(`Invalid key for this operation, its "alg" must be "${alg}" when present`);
27
17
  }
28
18
  if (Array.isArray(key.key_ops)) {
29
- const expectedKeyOp = usage === 'encrypt' || usage === 'decrypt' ? entry.keyOps?.[usage] : usage;
30
- if (expectedKeyOp && key.key_ops?.includes?.(expectedKeyOp) === false) {
19
+ const expectedKeyOp = usage === 'encrypt' || usage === 'decrypt' ? entry.ops?.[usage === 'encrypt' ? 0 : 1] : usage;
20
+ if (expectedKeyOp && !key.key_ops.includes(expectedKeyOp)) {
31
21
  throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${expectedKeyOp}" when present`);
32
22
  }
33
23
  }
34
- return true;
35
- };
36
- const symmetricTypeCheck = (entry, key, usage) => {
37
- const { alg } = entry;
38
- if (key instanceof Uint8Array)
39
- return { kind: BYTES, key };
40
- if (jwk.isJWK(key)) {
41
- if (jwk.isSecretJWK(key) && jwkMatchesOp(entry, key, usage))
42
- return { kind: JWK, key };
43
- 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`);
44
- }
45
- if (!isKeyLike(key)) {
46
- throw new TypeError(invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key', 'Uint8Array'));
47
- }
48
- if (key.type !== 'secret') {
49
- throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`);
50
- }
51
- return isCryptoKey(key) ? { kind: CRYPTO, key } : { kind: KEYOBJECT, key };
52
24
  };
53
- const asymmetricTypeCheck = (entry, key, usage) => {
54
- const { alg } = entry;
25
+ export function checkKeyType(entry, key, usage) {
26
+ const { alg, secret } = entry;
27
+ const privateKey = usage === 'decrypt' || usage === 'sign';
28
+ if (secret && key instanceof Uint8Array)
29
+ return [BYTES, key];
55
30
  if (jwk.isJWK(key)) {
56
- switch (usage) {
57
- case 'decrypt':
58
- case 'sign':
59
- if (jwk.isPrivateJWK(key) && jwkMatchesOp(entry, key, usage))
60
- return { kind: JWK, key };
61
- throw new TypeError(`JSON Web Key for this operation must be a private JWK`);
62
- case 'encrypt':
63
- case 'verify':
64
- if (jwk.isPublicJWK(key) && jwkMatchesOp(entry, key, usage))
65
- return { kind: JWK, key };
66
- throw new TypeError(`JSON Web Key for this operation must be a public JWK`);
31
+ if (secret ? !jwk.isSecretJWK(key) : !(privateKey ? jwk.isPrivateJWK(key) : jwk.isPublicJWK(key))) {
32
+ throw new TypeError(secret
33
+ ? `JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present`
34
+ : `JSON Web Key for this operation must be a ${privateKey ? 'private' : 'public'} JWK`);
67
35
  }
36
+ jwkMatchesOp(entry, key, usage);
37
+ return [JWK, key];
68
38
  }
69
39
  if (!isKeyLike(key)) {
70
- throw new TypeError(invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key'));
71
- }
72
- if (key.type === 'secret') {
73
- throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`);
40
+ throw new TypeError(secret
41
+ ? invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key', 'Uint8Array')
42
+ : invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key'));
74
43
  }
75
- if (key.type === 'public') {
76
- switch (usage) {
77
- case 'sign':
78
- throw new TypeError(`${tag(key)} instances for asymmetric algorithm signing must be of type "private"`);
79
- case 'decrypt':
80
- throw new TypeError(`${tag(key)} instances for asymmetric algorithm decryption must be of type "private"`);
44
+ if (secret) {
45
+ if (key.type !== 'secret') {
46
+ throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`);
81
47
  }
82
48
  }
83
- if (key.type === 'private') {
84
- switch (usage) {
85
- case 'verify':
86
- throw new TypeError(`${tag(key)} instances for asymmetric algorithm verifying must be of type "public"`);
87
- case 'encrypt':
88
- throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type "public"`);
49
+ else {
50
+ if (key.type === 'secret') {
51
+ throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`);
52
+ }
53
+ const expectedType = privateKey ? 'private' : 'public';
54
+ if ((key.type === 'public' || key.type === 'private') && key.type !== expectedType) {
55
+ const operation = usage === 'sign'
56
+ ? 'signing'
57
+ : usage === 'verify'
58
+ ? 'verifying'
59
+ : `${usage.slice(0, -1)}tion`;
60
+ throw new TypeError(`${tag(key)} instances for asymmetric algorithm ${operation} must be of type "${expectedType}"`);
89
61
  }
90
62
  }
91
- return isCryptoKey(key) ? { kind: CRYPTO, key } : { kind: KEYOBJECT, key };
92
- };
93
- const BYTES = Symbol();
94
- const CRYPTO = Symbol();
95
- const KEYOBJECT = Symbol();
96
- const JWK = Symbol();
97
- export function checkKeyType(entry, key, usage) {
98
- return entry.symmetric
99
- ? symmetricTypeCheck(entry, key, usage)
100
- : asymmetricTypeCheck(entry, key, usage);
63
+ return isCryptoKey(key) ? [CRYPTO, key] : [KEYOBJECT, key];
101
64
  }
65
+ const BYTES = 0;
66
+ const CRYPTO = 1;
67
+ const KEYOBJECT = 2;
68
+ const JWK = 3;
102
69
  let cache;
103
70
  const nist = {
104
71
  __proto__: null,
@@ -106,58 +73,53 @@ const nist = {
106
73
  secp384r1: 'P-384',
107
74
  secp521r1: 'P-521',
108
75
  };
109
- function cached(key, alg) {
76
+ function cached(key, alg, value) {
110
77
  cache ||= new WeakMap();
111
- return cache.get(key)?.[alg];
112
- }
113
- function store(key, alg, cryptoKey) {
114
78
  const entry = cache.get(key);
115
- if (entry) {
116
- entry[alg] = cryptoKey;
117
- }
118
- else {
119
- cache.set(key, { [alg]: cryptoKey });
79
+ if (value) {
80
+ if (entry) {
81
+ entry[alg] = value;
82
+ }
83
+ else {
84
+ cache.set(key, { [alg]: value });
85
+ }
120
86
  }
121
- return cryptoKey;
87
+ return value ?? entry?.[alg];
122
88
  }
123
- const handleJWK = async (key, jwk, entry) => {
124
- const hit = cached(key, entry.alg);
125
- if (hit)
126
- return hit;
127
- const cryptoKey = await jwkToKey(entry, { ...jwk, alg: entry.alg });
128
- return store(key, entry.alg, cryptoKey);
129
- };
89
+ const handleJWK = async (key, jwk, entry) => cached(key, entry.alg) ??
90
+ cached(key, entry.alg, await jwkToKey(entry, { ...jwk, alg: entry.alg }));
130
91
  const handleKeyObject = (keyObject, entry) => {
131
92
  const hit = cached(keyObject, entry.alg);
132
93
  if (hit)
133
94
  return hit;
134
95
  const isPublic = keyObject.type === 'public';
135
- const usages = isPublic ? entry.usages.public : entry.usages.private;
96
+ const usages = entry.usages[isPublic ? 0 : 1];
136
97
  const { asymmetricKeyType } = keyObject;
137
98
  const crv = nist[keyObject.asymmetricKeyDetails?.namedCurve];
138
- const params = entry.subtleFor?.({ crv, asymmetricKeyType }) ?? entry.subtle;
139
- return store(keyObject, entry.alg, keyObject.toCryptoKey(params, isPublic, usages));
99
+ const params = entry.resolve?.({ crv, asymmetricKeyType }) ?? entry.subtle;
100
+ return cached(keyObject, entry.alg, keyObject.toCryptoKey(params, isPublic, usages));
140
101
  };
141
102
  export async function prepareKey(entry, key, usage) {
142
103
  const tagged = checkKeyType(entry, key, usage);
143
- switch (tagged.kind) {
104
+ switch (tagged[0]) {
144
105
  case BYTES:
145
106
  case CRYPTO:
146
- return tagged.key;
107
+ return tagged[1];
147
108
  case JWK: {
148
- if (tagged.key.k) {
149
- return decode(tagged.key.k);
109
+ const key = tagged[1];
110
+ if (key.k) {
111
+ return decode(key.k);
150
112
  }
151
- if (!Object.isFrozen(tagged.key)) {
152
- const { key_ops } = tagged.key;
113
+ if (!Object.isFrozen(key)) {
114
+ const { key_ops } = key;
153
115
  if (Array.isArray(key_ops))
154
116
  Object.freeze(key_ops);
155
- Object.freeze(tagged.key);
117
+ Object.freeze(key);
156
118
  }
157
- return handleJWK(tagged.key, tagged.key, entry);
119
+ return handleJWK(key, key, entry);
158
120
  }
159
121
  case KEYOBJECT: {
160
- const keyObject = tagged.key;
122
+ const keyObject = tagged[1];
161
123
  if (keyObject.type === 'secret') {
162
124
  return keyObject.export();
163
125
  }
@@ -1,16 +1,10 @@
1
1
  import { JOSENotSupported } from '../util/errors.js';
2
2
  import { maybeJWSAlgorithm } from './jws_algorithms.js';
3
3
  import { maybeJWEAlgorithm } from './jwe_algorithms.js';
4
- function unsupportedAlgorithm() {
5
- return new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
6
- }
7
4
  export function keyAlgorithm(alg) {
8
- if (typeof alg !== 'string') {
9
- throw unsupportedAlgorithm();
10
- }
11
- const entry = maybeJWSAlgorithm(alg) ?? maybeJWEAlgorithm(alg);
5
+ const entry = typeof alg === 'string' ? (maybeJWSAlgorithm(alg) ?? maybeJWEAlgorithm(alg)) : undefined;
12
6
  if (!entry) {
13
- throw unsupportedAlgorithm();
7
+ throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
14
8
  }
15
9
  return entry;
16
10
  }
@@ -1,6 +1,6 @@
1
1
  export function table(entries) {
2
2
  const out = { __proto__: null };
3
- for (const alg of Object.keys(entries)) {
3
+ for (const alg in entries) {
4
4
  out[alg] = { ...entries[alg], alg };
5
5
  }
6
6
  return out;
@@ -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
  }