@suveren/gateway 0.4.1 → 0.6.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 (137) hide show
  1. package/bin/suveren-gateway.js +86 -5
  2. package/content/integrations/calendar.json +116 -22
  3. package/content/integrations/deploy-github.json +164 -0
  4. package/content/integrations/gmail.json +13 -4
  5. package/content/integrations/index.json +2 -1
  6. package/dist/control-plane/index.mjs +84 -7
  7. package/dist/mcp-server/http.mjs +147 -21
  8. package/dist/ui/assets/index-DecSrutK.js +105 -0
  9. package/dist/ui/index.html +1 -1
  10. package/node_modules/@hap/core/dist/index.d.mts +21 -0
  11. package/node_modules/@hap/core/dist/index.d.ts +21 -0
  12. package/node_modules/@hap/core/dist/index.js +17 -0
  13. package/node_modules/@hap/core/dist/index.mjs +17 -0
  14. package/node_modules/@hap/core/package.json +1 -1
  15. package/node_modules/@hap/core/src/gatekeeper.ts +28 -0
  16. package/node_modules/@hap/core/src/types.ts +21 -0
  17. package/node_modules/fast-uri/index.js +37 -1
  18. package/node_modules/fast-uri/package.json +1 -1
  19. package/node_modules/fast-uri/test/security.test.js +136 -0
  20. package/node_modules/hono/dist/cjs/helper/proxy/index.js +4 -0
  21. package/node_modules/hono/dist/cjs/jsx/base.js +1 -9
  22. package/node_modules/hono/dist/cjs/jsx/hooks/index.js +14 -11
  23. package/node_modules/hono/dist/cjs/middleware/cors/index.js +1 -1
  24. package/node_modules/hono/dist/cjs/middleware/language/language.js +10 -6
  25. package/node_modules/hono/dist/cjs/utils/cookie.js +2 -1
  26. package/node_modules/hono/dist/helper/proxy/index.js +4 -0
  27. package/node_modules/hono/dist/jsx/base.js +1 -9
  28. package/node_modules/hono/dist/jsx/hooks/index.js +14 -11
  29. package/node_modules/hono/dist/middleware/cors/index.js +1 -1
  30. package/node_modules/hono/dist/middleware/language/language.js +10 -6
  31. package/node_modules/hono/dist/utils/cookie.js +2 -1
  32. package/node_modules/hono/package.json +2 -3
  33. package/node_modules/ip-address/README.md +142 -128
  34. package/node_modules/ip-address/dist/common.d.ts +6 -0
  35. package/node_modules/ip-address/dist/common.js +17 -1
  36. package/node_modules/ip-address/dist/common.js.map +1 -1
  37. package/node_modules/ip-address/dist/ipv4.js +3 -12
  38. package/node_modules/ip-address/dist/ipv4.js.map +1 -1
  39. package/node_modules/ip-address/dist/ipv6.d.ts +9 -2
  40. package/node_modules/ip-address/dist/ipv6.js +35 -16
  41. package/node_modules/ip-address/dist/ipv6.js.map +1 -1
  42. package/node_modules/ip-address/package.json +5 -3
  43. package/node_modules/jose/README.md +13 -13
  44. package/node_modules/jose/dist/types/index.d.ts +6 -5
  45. package/node_modules/jose/dist/types/jwe/compact/decrypt.d.ts +17 -11
  46. package/node_modules/jose/dist/types/jwe/compact/encrypt.d.ts +7 -19
  47. package/node_modules/jose/dist/types/jwe/flattened/decrypt.d.ts +17 -11
  48. package/node_modules/jose/dist/types/jwe/flattened/encrypt.d.ts +7 -19
  49. package/node_modules/jose/dist/types/jwe/general/decrypt.d.ts +18 -13
  50. package/node_modules/jose/dist/types/jwe/general/encrypt.d.ts +20 -21
  51. package/node_modules/jose/dist/types/jwk/embedded.d.ts +8 -12
  52. package/node_modules/jose/dist/types/jwk/thumbprint.d.ts +0 -15
  53. package/node_modules/jose/dist/types/jwks/local.d.ts +12 -21
  54. package/node_modules/jose/dist/types/jwks/remote.d.ts +34 -165
  55. package/node_modules/jose/dist/types/jws/compact/sign.d.ts +2 -13
  56. package/node_modules/jose/dist/types/jws/compact/verify.d.ts +17 -13
  57. package/node_modules/jose/dist/types/jws/flattened/sign.d.ts +2 -13
  58. package/node_modules/jose/dist/types/jws/flattened/verify.d.ts +17 -13
  59. package/node_modules/jose/dist/types/jws/general/sign.d.ts +16 -17
  60. package/node_modules/jose/dist/types/jws/general/verify.d.ts +18 -15
  61. package/node_modules/jose/dist/types/jwt/decrypt.d.ts +17 -11
  62. package/node_modules/jose/dist/types/jwt/encrypt.d.ts +10 -34
  63. package/node_modules/jose/dist/types/jwt/sign.d.ts +2 -13
  64. package/node_modules/jose/dist/types/jwt/unsecured.d.ts +4 -13
  65. package/node_modules/jose/dist/types/jwt/verify.d.ts +14 -13
  66. package/node_modules/jose/dist/types/key/export.d.ts +0 -14
  67. package/node_modules/jose/dist/types/key/generate_key_pair.d.ts +7 -14
  68. package/node_modules/jose/dist/types/key/generate_secret.d.ts +16 -14
  69. package/node_modules/jose/dist/types/key/import.d.ts +18 -28
  70. package/node_modules/jose/dist/types/types.d.ts +239 -222
  71. package/node_modules/jose/dist/types/util/base64url.d.ts +11 -4
  72. package/node_modules/jose/dist/types/util/decode_jwt.d.ts +1 -9
  73. package/node_modules/jose/dist/types/util/decode_protected_header.d.ts +0 -8
  74. package/node_modules/jose/dist/types/util/errors.d.ts +128 -121
  75. package/node_modules/jose/dist/webapi/jwe/compact/decrypt.js +4 -22
  76. package/node_modules/jose/dist/webapi/jwe/flattened/decrypt.js +5 -153
  77. package/node_modules/jose/dist/webapi/jwe/flattened/encrypt.js +16 -111
  78. package/node_modules/jose/dist/webapi/jwe/general/decrypt.js +15 -3
  79. package/node_modules/jose/dist/webapi/jwe/general/encrypt.js +65 -81
  80. package/node_modules/jose/dist/webapi/jwk/embedded.js +5 -3
  81. package/node_modules/jose/dist/webapi/jwks/local.js +31 -72
  82. package/node_modules/jose/dist/webapi/jwks/remote.js +19 -28
  83. package/node_modules/jose/dist/webapi/jws/compact/sign.js +5 -2
  84. package/node_modules/jose/dist/webapi/jws/compact/verify.js +4 -16
  85. package/node_modules/jose/dist/webapi/jws/flattened/sign.js +7 -65
  86. package/node_modules/jose/dist/webapi/jws/flattened/verify.js +3 -89
  87. package/node_modules/jose/dist/webapi/jws/general/sign.js +19 -15
  88. package/node_modules/jose/dist/webapi/jws/general/verify.js +29 -9
  89. package/node_modules/jose/dist/webapi/jwt/decrypt.js +5 -5
  90. package/node_modules/jose/dist/webapi/jwt/sign.js +2 -3
  91. package/node_modules/jose/dist/webapi/jwt/unsecured.js +4 -3
  92. package/node_modules/jose/dist/webapi/jwt/verify.js +6 -6
  93. package/node_modules/jose/dist/webapi/key/export.js +37 -4
  94. package/node_modules/jose/dist/webapi/key/generate_key_pair.js +33 -82
  95. package/node_modules/jose/dist/webapi/key/import.js +8 -8
  96. package/node_modules/jose/dist/webapi/lib/asn1.js +53 -122
  97. package/node_modules/jose/dist/webapi/lib/buffer_utils.js +1 -0
  98. package/node_modules/jose/dist/webapi/lib/content_encryption.js +34 -109
  99. package/node_modules/jose/dist/webapi/lib/crypto_key.js +18 -126
  100. package/node_modules/jose/dist/webapi/lib/helpers.js +23 -0
  101. package/node_modules/jose/dist/webapi/lib/invalid_key_input.js +0 -1
  102. package/node_modules/jose/dist/webapi/lib/jwe_algorithms.js +116 -0
  103. package/node_modules/jose/dist/webapi/lib/jwe_decrypt.js +186 -0
  104. package/node_modules/jose/dist/webapi/lib/jwe_encrypt.js +110 -0
  105. package/node_modules/jose/dist/webapi/lib/jwk_to_key.js +8 -98
  106. package/node_modules/jose/dist/webapi/lib/jws_algorithms.js +76 -0
  107. package/node_modules/jose/dist/webapi/lib/jws_sign.js +74 -0
  108. package/node_modules/jose/dist/webapi/lib/jws_verify.js +107 -0
  109. package/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +68 -109
  110. package/node_modules/jose/dist/webapi/lib/key.js +132 -0
  111. package/node_modules/jose/dist/webapi/lib/key_algorithm.js +10 -0
  112. package/node_modules/jose/dist/webapi/lib/key_descriptor.js +7 -0
  113. package/node_modules/jose/dist/webapi/lib/key_management.js +162 -92
  114. package/node_modules/jose/dist/webapi/lib/options.js +48 -0
  115. package/node_modules/jose/dist/webapi/lib/signing.js +14 -56
  116. package/node_modules/jose/dist/webapi/lib/type_checks.js +13 -18
  117. package/node_modules/jose/dist/webapi/util/base64url.js +13 -4
  118. package/node_modules/jose/dist/webapi/util/decode_jwt.js +2 -2
  119. package/node_modules/jose/dist/webapi/util/decode_protected_header.js +5 -15
  120. package/node_modules/jose/dist/webapi/util/errors.js +1 -1
  121. package/node_modules/jose/package.json +2 -4
  122. package/package.json +2 -2
  123. package/profiles/deploy/0.6.profile.json +168 -0
  124. package/profiles/deploy/0.7.profile.json +168 -0
  125. package/profiles/email/0.4.profile.json +9 -2
  126. package/profiles/index.json +3 -1
  127. package/dist/ui/assets/index-Cog54HOo.js +0 -105
  128. package/node_modules/jose/dist/webapi/lib/aesgcmkw.js +0 -15
  129. package/node_modules/jose/dist/webapi/lib/aeskw.js +0 -25
  130. package/node_modules/jose/dist/webapi/lib/check_key_type.js +0 -122
  131. package/node_modules/jose/dist/webapi/lib/ecdhes.js +0 -52
  132. package/node_modules/jose/dist/webapi/lib/key_to_jwk.js +0 -34
  133. package/node_modules/jose/dist/webapi/lib/normalize_key.js +0 -166
  134. package/node_modules/jose/dist/webapi/lib/pbes2kw.js +0 -42
  135. package/node_modules/jose/dist/webapi/lib/rsaes.js +0 -24
  136. package/node_modules/jose/dist/webapi/lib/validate_algorithms.js +0 -10
  137. package/node_modules/jose/dist/webapi/lib/validate_crit.js +0 -33
@@ -1,14 +1,7 @@
1
- import { encode as b64u } from '../../util/base64url.js';
2
1
  import { unprotected, assertNotSet } from '../../lib/helpers.js';
3
- import { encrypt } from '../../lib/content_encryption.js';
4
- import { encryptKeyManagement } from '../../lib/key_management.js';
5
- import { JOSENotSupported, JWEInvalid } from '../../util/errors.js';
6
- import { isDisjoint } from '../../lib/type_checks.js';
7
- import { concat, encode } from '../../lib/buffer_utils.js';
8
- import { validateCrit } from '../../lib/validate_crit.js';
9
- import { normalizeKey } from '../../lib/normalize_key.js';
10
- import { checkKeyType } from '../../lib/check_key_type.js';
11
- import { compress } from '../../lib/deflate.js';
2
+ import { JWEInvalid } from '../../util/errors.js';
3
+ import { createJWE } from '../../lib/jwe_encrypt.js';
4
+ import { validateCritDuplicates } from '../../lib/options.js';
12
5
  export class FlattenedEncrypt {
13
6
  #plaintext;
14
7
  #protectedHeader;
@@ -62,106 +55,18 @@ export class FlattenedEncrypt {
62
55
  if (!this.#protectedHeader && !this.#unprotectedHeader && !this.#sharedUnprotectedHeader) {
63
56
  throw new JWEInvalid('either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()');
64
57
  }
65
- if (!isDisjoint(this.#protectedHeader, this.#unprotectedHeader, this.#sharedUnprotectedHeader)) {
66
- throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint');
67
- }
68
- const joseHeader = {
69
- ...this.#protectedHeader,
70
- ...this.#unprotectedHeader,
71
- ...this.#sharedUnprotectedHeader,
72
- };
73
- validateCrit(JWEInvalid, new Map(), options?.crit, this.#protectedHeader, joseHeader);
74
- if (joseHeader.zip !== undefined && joseHeader.zip !== 'DEF') {
75
- throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value.');
76
- }
77
- if (joseHeader.zip !== undefined && !this.#protectedHeader?.zip) {
78
- throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header Parameter MUST be in a protected header.');
79
- }
80
- const { alg, enc } = joseHeader;
81
- if (typeof alg !== 'string' || !alg) {
82
- throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid');
83
- }
84
- if (typeof enc !== 'string' || !enc) {
85
- throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');
86
- }
87
- let encryptedKey;
88
- if (this.#cek && (alg === 'dir' || alg === 'ECDH-ES')) {
89
- throw new TypeError(`setContentEncryptionKey cannot be called with JWE "alg" (Algorithm) Header ${alg}`);
90
- }
91
- checkKeyType(alg === 'dir' ? enc : alg, key, 'encrypt');
92
- let cek;
93
- {
94
- let parameters;
95
- const k = await normalizeKey(key, alg);
96
- ({ cek, encryptedKey, parameters } = await encryptKeyManagement(alg, enc, k, this.#cek, this.#keyManagementParameters));
97
- if (parameters) {
98
- if (options && unprotected in options) {
99
- if (!this.#unprotectedHeader) {
100
- this.setUnprotectedHeader(parameters);
101
- }
102
- else {
103
- this.#unprotectedHeader = { ...this.#unprotectedHeader, ...parameters };
104
- }
105
- }
106
- else if (!this.#protectedHeader) {
107
- this.setProtectedHeader(parameters);
108
- }
109
- else {
110
- this.#protectedHeader = { ...this.#protectedHeader, ...parameters };
111
- }
112
- }
113
- }
114
- let additionalData;
115
- let protectedHeaderS;
116
- let protectedHeaderB;
117
- let aadMember;
118
- if (this.#protectedHeader) {
119
- protectedHeaderS = b64u(JSON.stringify(this.#protectedHeader));
120
- protectedHeaderB = encode(protectedHeaderS);
121
- }
122
- else {
123
- protectedHeaderS = '';
124
- protectedHeaderB = new Uint8Array();
125
- }
126
- if (this.#aad) {
127
- aadMember = b64u(this.#aad);
128
- const aadMemberBytes = encode(aadMember);
129
- additionalData = concat(protectedHeaderB, encode('.'), aadMemberBytes);
130
- }
131
- else {
132
- additionalData = protectedHeaderB;
133
- }
134
- let plaintext = this.#plaintext;
135
- if (joseHeader.zip === 'DEF') {
136
- plaintext = await compress(plaintext).catch((cause) => {
137
- throw new JWEInvalid('Failed to compress plaintext', { cause });
138
- });
139
- }
140
- const { ciphertext, tag, iv } = await encrypt(enc, plaintext, cek, this.#iv, additionalData);
141
- const jwe = {
142
- ciphertext: b64u(ciphertext),
143
- };
144
- if (iv) {
145
- jwe.iv = b64u(iv);
146
- }
147
- if (tag) {
148
- jwe.tag = b64u(tag);
149
- }
150
- if (encryptedKey) {
151
- jwe.encrypted_key = b64u(encryptedKey);
152
- }
153
- if (aadMember) {
154
- jwe.aad = aadMember;
155
- }
156
- if (this.#protectedHeader) {
157
- jwe.protected = protectedHeaderS;
158
- }
159
- if (this.#sharedUnprotectedHeader) {
160
- jwe.unprotected = this.#sharedUnprotectedHeader;
161
- }
162
- if (this.#unprotectedHeader) {
163
- jwe.header = this.#unprotectedHeader;
164
- }
165
- return jwe;
58
+ validateCritDuplicates(JWEInvalid, this.#protectedHeader);
59
+ return createJWE([
60
+ this.#plaintext,
61
+ this.#protectedHeader,
62
+ this.#unprotectedHeader,
63
+ this.#sharedUnprotectedHeader,
64
+ this.#aad,
65
+ this.#cek,
66
+ this.#iv,
67
+ this.#keyManagementParameters,
68
+ options?.crit,
69
+ options ? unprotected in options : false,
70
+ ], key);
166
71
  }
167
72
  }
@@ -1,4 +1,4 @@
1
- import { flattenedDecrypt } from '../flattened/decrypt.js';
1
+ import { prepareDecrypt, shareJWE, decryptRecipient, decryptResult, checkShared, checkRecipient, } from '../../lib/jwe_decrypt.js';
2
2
  import { JWEDecryptionFailed, JWEInvalid } from '../../util/errors.js';
3
3
  import { isObject } from '../../lib/type_checks.js';
4
4
  export async function generalDecrypt(jwe, key, options) {
@@ -11,9 +11,19 @@ export async function generalDecrypt(jwe, key, options) {
11
11
  if (!jwe.recipients.length) {
12
12
  throw new JWEInvalid('JWE Recipients has no members');
13
13
  }
14
+ let shared;
15
+ let token;
16
+ try {
17
+ checkShared(jwe);
18
+ shared = prepareDecrypt(options);
19
+ token = shareJWE(jwe);
20
+ }
21
+ catch {
22
+ throw new JWEDecryptionFailed();
23
+ }
14
24
  for (const recipient of jwe.recipients) {
15
25
  try {
16
- return await flattenedDecrypt({
26
+ const flattened = {
17
27
  aad: jwe.aad,
18
28
  ciphertext: jwe.ciphertext,
19
29
  encrypted_key: recipient.encrypted_key,
@@ -22,7 +32,9 @@ export async function generalDecrypt(jwe, key, options) {
22
32
  protected: jwe.protected,
23
33
  tag: jwe.tag,
24
34
  unprotected: jwe.unprotected,
25
- }, key, options);
35
+ };
36
+ checkRecipient(flattened);
37
+ return decryptResult(flattened, await decryptRecipient(flattened, token, shared, key));
26
38
  }
27
39
  catch {
28
40
  }
@@ -1,32 +1,28 @@
1
1
  import { FlattenedEncrypt } from '../flattened/encrypt.js';
2
- import { unprotected, assertNotSet } from '../../lib/helpers.js';
3
- import { JOSENotSupported, JWEInvalid } from '../../util/errors.js';
2
+ import { assertNotSet } from '../../lib/helpers.js';
3
+ import { JWEInvalid } from '../../util/errors.js';
4
4
  import { generateCek } from '../../lib/content_encryption.js';
5
- import { isDisjoint } from '../../lib/type_checks.js';
6
5
  import { encryptKeyManagement } from '../../lib/key_management.js';
7
6
  import { encode as b64u } from '../../util/base64url.js';
8
- import { validateCrit } from '../../lib/validate_crit.js';
9
- import { normalizeKey } from '../../lib/normalize_key.js';
10
- import { checkKeyType } from '../../lib/check_key_type.js';
7
+ import { validateCritDuplicates } from '../../lib/options.js';
8
+ import { checkEncryptHeaders, encryptJWE } from '../../lib/jwe_encrypt.js';
9
+ import { prepareKey } from '../../lib/key.js';
10
+ import { jweAlgorithm } from '../../lib/jwe_algorithms.js';
11
11
  class IndividualRecipient {
12
12
  #parent;
13
- unprotectedHeader;
14
- keyManagementParameters;
15
- key;
16
- options;
17
- constructor(enc, key, options) {
13
+ state;
14
+ constructor(enc, key, crit) {
18
15
  this.#parent = enc;
19
- this.key = key;
20
- this.options = options;
16
+ this.state = [undefined, undefined, key, crit];
21
17
  }
22
18
  setUnprotectedHeader(unprotectedHeader) {
23
- assertNotSet(this.unprotectedHeader, 'setUnprotectedHeader');
24
- this.unprotectedHeader = unprotectedHeader;
19
+ assertNotSet(this.state[0], 'setUnprotectedHeader');
20
+ this.state[0] = unprotectedHeader;
25
21
  return this;
26
22
  }
27
23
  setKeyManagementParameters(parameters) {
28
- assertNotSet(this.keyManagementParameters, 'setKeyManagementParameters');
29
- this.keyManagementParameters = parameters;
24
+ assertNotSet(this.state[1], 'setKeyManagementParameters');
25
+ this.state[1] = parameters;
30
26
  return this;
31
27
  }
32
28
  addRecipient(...args) {
@@ -39,6 +35,17 @@ class IndividualRecipient {
39
35
  return this.#parent;
40
36
  }
41
37
  }
38
+ function copyOptionalMembers(flattened, jwe, recipient) {
39
+ const { aad, protected: protectedHeader, unprotected, header } = flattened;
40
+ if (aad)
41
+ jwe.aad = aad;
42
+ if (protectedHeader)
43
+ jwe.protected = protectedHeader;
44
+ if (unprotected)
45
+ jwe.unprotected = unprotected;
46
+ if (header)
47
+ recipient.header = header;
48
+ }
42
49
  export class GeneralEncrypt {
43
50
  #plaintext;
44
51
  #recipients = [];
@@ -49,7 +56,7 @@ export class GeneralEncrypt {
49
56
  this.#plaintext = plaintext;
50
57
  }
51
58
  addRecipient(key, options) {
52
- const recipient = new IndividualRecipient(this, key, { crit: options?.crit });
59
+ const recipient = new IndividualRecipient(this, key, options?.crit);
53
60
  this.#recipients.push(recipient);
54
61
  return recipient;
55
62
  }
@@ -71,111 +78,88 @@ export class GeneralEncrypt {
71
78
  if (!this.#recipients.length) {
72
79
  throw new JWEInvalid('at least one recipient must be added');
73
80
  }
81
+ if (!(this.#plaintext instanceof Uint8Array)) {
82
+ throw new TypeError('plaintext must be an instance of Uint8Array');
83
+ }
74
84
  if (this.#recipients.length === 1) {
75
85
  const [recipient] = this.#recipients;
86
+ const [unprotectedHeader, keyManagementParameters, key, crit] = recipient.state;
76
87
  const flattened = await new FlattenedEncrypt(this.#plaintext)
77
88
  .setAdditionalAuthenticatedData(this.#aad)
78
89
  .setProtectedHeader(this.#protectedHeader)
79
90
  .setSharedUnprotectedHeader(this.#unprotectedHeader)
80
- .setUnprotectedHeader(recipient.unprotectedHeader)
81
- .encrypt(recipient.key, { ...recipient.options });
91
+ .setUnprotectedHeader(unprotectedHeader)
92
+ .setKeyManagementParameters(keyManagementParameters)
93
+ .encrypt(key, { crit });
82
94
  const jwe = {
83
95
  ciphertext: flattened.ciphertext,
84
96
  iv: flattened.iv,
85
97
  recipients: [{}],
86
98
  tag: flattened.tag,
87
99
  };
88
- if (flattened.aad)
89
- jwe.aad = flattened.aad;
90
- if (flattened.protected)
91
- jwe.protected = flattened.protected;
92
- if (flattened.unprotected)
93
- jwe.unprotected = flattened.unprotected;
94
100
  if (flattened.encrypted_key)
95
101
  jwe.recipients[0].encrypted_key = flattened.encrypted_key;
96
- if (flattened.header)
97
- jwe.recipients[0].header = flattened.header;
102
+ copyOptionalMembers(flattened, jwe, jwe.recipients[0]);
98
103
  return jwe;
99
104
  }
105
+ validateCritDuplicates(JWEInvalid, this.#protectedHeader);
100
106
  let enc;
107
+ const inputs = [];
108
+ const checked = [];
101
109
  for (let i = 0; i < this.#recipients.length; i++) {
102
110
  const recipient = this.#recipients[i];
103
- if (!isDisjoint(this.#protectedHeader, this.#unprotectedHeader, recipient.unprotectedHeader)) {
104
- throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint');
105
- }
106
- const joseHeader = {
107
- ...this.#protectedHeader,
108
- ...this.#unprotectedHeader,
109
- ...recipient.unprotectedHeader,
110
- };
111
- const { alg } = joseHeader;
112
- if (typeof alg !== 'string' || !alg) {
113
- throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid');
114
- }
115
- if (alg === 'dir' || alg === 'ECDH-ES') {
111
+ const [unprotectedHeader, keyManagementParameters, , crit] = recipient.state;
112
+ const input = [
113
+ this.#plaintext,
114
+ this.#protectedHeader,
115
+ unprotectedHeader,
116
+ this.#unprotectedHeader,
117
+ this.#aad,
118
+ undefined,
119
+ undefined,
120
+ keyManagementParameters,
121
+ crit,
122
+ true,
123
+ ];
124
+ const headers = checkEncryptHeaders(input);
125
+ inputs.push(input);
126
+ checked.push(headers);
127
+ if (headers[1] === 'dir' || headers[1] === 'ECDH-ES') {
116
128
  throw new JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient');
117
129
  }
118
- if (typeof joseHeader.enc !== 'string' || !joseHeader.enc) {
119
- throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');
120
- }
121
130
  if (!enc) {
122
- enc = joseHeader.enc;
131
+ enc = headers[2];
123
132
  }
124
- else if (enc !== joseHeader.enc) {
133
+ else if (enc !== headers[2]) {
125
134
  throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients');
126
135
  }
127
- validateCrit(JWEInvalid, new Map(), recipient.options.crit, this.#protectedHeader, joseHeader);
128
- if (joseHeader.zip !== undefined && joseHeader.zip !== 'DEF') {
129
- throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value.');
130
- }
131
- if (joseHeader.zip !== undefined && !this.#protectedHeader?.zip) {
132
- throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header Parameter MUST be in a protected header.');
133
- }
134
136
  }
135
- const cek = generateCek(enc);
137
+ const cek = generateCek(checked[0][3]);
136
138
  const jwe = {
137
139
  ciphertext: '',
138
140
  recipients: [],
139
141
  };
140
142
  for (let i = 0; i < this.#recipients.length; i++) {
141
143
  const recipient = this.#recipients[i];
144
+ const [unprotectedHeader, keyManagementParameters, key] = recipient.state;
142
145
  const target = {};
143
146
  jwe.recipients.push(target);
144
147
  if (i === 0) {
145
- const flattened = await new FlattenedEncrypt(this.#plaintext)
146
- .setAdditionalAuthenticatedData(this.#aad)
147
- .setContentEncryptionKey(cek)
148
- .setProtectedHeader(this.#protectedHeader)
149
- .setSharedUnprotectedHeader(this.#unprotectedHeader)
150
- .setUnprotectedHeader(recipient.unprotectedHeader)
151
- .setKeyManagementParameters(recipient.keyManagementParameters)
152
- .encrypt(recipient.key, {
153
- ...recipient.options,
154
- [unprotected]: true,
155
- });
148
+ inputs[0][5] = cek;
149
+ const flattened = await encryptJWE(inputs[0], checked[0], key);
156
150
  jwe.ciphertext = flattened.ciphertext;
157
151
  jwe.iv = flattened.iv;
158
152
  jwe.tag = flattened.tag;
159
- if (flattened.aad)
160
- jwe.aad = flattened.aad;
161
- if (flattened.protected)
162
- jwe.protected = flattened.protected;
163
- if (flattened.unprotected)
164
- jwe.unprotected = flattened.unprotected;
165
153
  target.encrypted_key = flattened.encrypted_key;
166
- if (flattened.header)
167
- target.header = flattened.header;
154
+ copyOptionalMembers(flattened, jwe, target);
168
155
  continue;
169
156
  }
170
- const alg = recipient.unprotectedHeader?.alg ||
171
- this.#protectedHeader?.alg ||
172
- this.#unprotectedHeader?.alg;
173
- checkKeyType(alg === 'dir' ? enc : alg, recipient.key, 'encrypt');
174
- const k = await normalizeKey(recipient.key, alg);
175
- const { encryptedKey, parameters } = await encryptKeyManagement(alg, enc, k, cek, recipient.keyManagementParameters);
157
+ const [, alg, , encEntry] = checked[i];
158
+ const k = await prepareKey(jweAlgorithm(alg), key, 'encrypt');
159
+ const [, encryptedKey, parameters] = await encryptKeyManagement(alg, encEntry, k, cek, keyManagementParameters);
176
160
  target.encrypted_key = b64u(encryptedKey);
177
- if (recipient.unprotectedHeader || parameters)
178
- target.header = { ...recipient.unprotectedHeader, ...parameters };
161
+ if (unprotectedHeader || parameters)
162
+ target.header = { ...unprotectedHeader, ...parameters };
179
163
  }
180
164
  return jwe;
181
165
  }
@@ -1,4 +1,5 @@
1
- import { importJWK } from '../key/import.js';
1
+ import { jwkToKey } from '../lib/jwk_to_key.js';
2
+ import { jwsAlgorithm } from '../lib/jws_algorithms.js';
2
3
  import { isObject } from '../lib/type_checks.js';
3
4
  import { JWSInvalid } from '../util/errors.js';
4
5
  export async function EmbeddedJWK(protectedHeader, token) {
@@ -9,8 +10,9 @@ export async function EmbeddedJWK(protectedHeader, token) {
9
10
  if (!isObject(joseHeader.jwk)) {
10
11
  throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object');
11
12
  }
12
- const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg);
13
- if (key instanceof Uint8Array || key.type !== 'public') {
13
+ const entry = jwsAlgorithm(joseHeader.alg);
14
+ const key = await jwkToKey(entry, { ...joseHeader.jwk, ext: true });
15
+ if (key.type !== 'public') {
14
16
  throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key');
15
17
  }
16
18
  return key;
@@ -1,31 +1,22 @@
1
- import { importJWK } from '../key/import.js';
1
+ import { jwkToKey } from '../lib/jwk_to_key.js';
2
+ import { maybeJWSAlgorithm } from '../lib/jws_algorithms.js';
2
3
  import { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js';
3
4
  import { isObject } from '../lib/type_checks.js';
4
- function getKtyFromAlg(alg) {
5
- switch (typeof alg === 'string' && alg.slice(0, 2)) {
6
- case 'RS':
7
- case 'PS':
8
- return 'RSA';
9
- case 'ES':
10
- return 'EC';
11
- case 'Ed':
12
- return 'OKP';
13
- case 'ML':
14
- return 'AKP';
15
- default:
16
- throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set');
5
+ function signatureAlgorithm(alg) {
6
+ const entry = typeof alg === 'string' ? maybeJWSAlgorithm(alg) : undefined;
7
+ if (!entry || entry.secret) {
8
+ throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set');
17
9
  }
10
+ return entry;
18
11
  }
19
12
  function isJWKSLike(jwks) {
20
- return (jwks &&
21
- typeof jwks === 'object' &&
22
- Array.isArray(jwks.keys) &&
23
- jwks.keys.every(isJWKLike));
24
- }
25
- function isJWKLike(key) {
26
- return isObject(key);
13
+ if (!jwks || typeof jwks !== 'object') {
14
+ return false;
15
+ }
16
+ const { keys } = jwks;
17
+ return Array.isArray(keys) && keys.every((isObject));
27
18
  }
28
- class LocalJWKSet {
19
+ class LocalJWKSetImpl {
29
20
  #jwks;
30
21
  #cached = new WeakMap();
31
22
  constructor(jwks) {
@@ -39,40 +30,13 @@ class LocalJWKSet {
39
30
  }
40
31
  async getKey(protectedHeader, token) {
41
32
  const { alg, kid } = { ...protectedHeader, ...token?.header };
42
- const kty = getKtyFromAlg(alg);
43
- const candidates = this.#jwks.keys.filter((jwk) => {
44
- let candidate = kty === jwk.kty;
45
- if (candidate && typeof kid === 'string') {
46
- candidate = kid === jwk.kid;
47
- }
48
- if (candidate && (typeof jwk.alg === 'string' || kty === 'AKP')) {
49
- candidate = alg === jwk.alg;
50
- }
51
- if (candidate && typeof jwk.use === 'string') {
52
- candidate = jwk.use === 'sig';
53
- }
54
- if (candidate && Array.isArray(jwk.key_ops)) {
55
- candidate = jwk.key_ops.includes('verify');
56
- }
57
- if (candidate) {
58
- switch (alg) {
59
- case 'ES256':
60
- candidate = jwk.crv === 'P-256';
61
- break;
62
- case 'ES384':
63
- candidate = jwk.crv === 'P-384';
64
- break;
65
- case 'ES512':
66
- candidate = jwk.crv === 'P-521';
67
- break;
68
- case 'Ed25519':
69
- case 'EdDSA':
70
- candidate = jwk.crv === 'Ed25519';
71
- break;
72
- }
73
- }
74
- return candidate;
75
- });
33
+ const entry = signatureAlgorithm(alg);
34
+ const candidates = this.#jwks.keys.filter((jwk) => entry.kty.includes(jwk.kty) &&
35
+ (typeof kid !== 'string' || kid === jwk.kid) &&
36
+ (!(typeof jwk.alg === 'string' || jwk.kty === 'AKP') || alg === jwk.alg) &&
37
+ (typeof jwk.use !== 'string' || jwk.use === 'sig') &&
38
+ (!Array.isArray(jwk.key_ops) || jwk.key_ops.includes('verify')) &&
39
+ (!entry.crv || jwk.crv === entry.crv));
76
40
  const { 0: jwk, length } = candidates;
77
41
  if (length === 0) {
78
42
  throw new JWKSNoMatchingKey();
@@ -83,37 +47,32 @@ class LocalJWKSet {
83
47
  error[Symbol.asyncIterator] = async function* () {
84
48
  for (const jwk of candidates) {
85
49
  try {
86
- yield await importWithAlgCache(_cached, jwk, alg);
50
+ yield await importWithAlgCache(_cached, jwk, entry);
87
51
  }
88
52
  catch { }
89
53
  }
90
54
  };
91
55
  throw error;
92
56
  }
93
- return importWithAlgCache(this.#cached, jwk, alg);
57
+ return importWithAlgCache(this.#cached, jwk, entry);
94
58
  }
95
59
  }
96
- async function importWithAlgCache(cache, jwk, alg) {
60
+ async function importWithAlgCache(cache, jwk, entry) {
97
61
  const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk);
98
- if (cached[alg] === undefined) {
99
- const key = await importJWK({ ...jwk, ext: true }, alg);
100
- if (key instanceof Uint8Array || key.type !== 'public') {
62
+ if (cached[entry.alg] === undefined) {
63
+ const key = await jwkToKey(entry, { ...jwk, alg: entry.alg, ext: true });
64
+ if (key.type !== 'public') {
101
65
  throw new JWKSInvalid('JSON Web Key Set members must be public keys');
102
66
  }
103
- cached[alg] = key;
67
+ cached[entry.alg] = key;
104
68
  }
105
- return cached[alg];
69
+ return cached[entry.alg];
106
70
  }
107
71
  export function createLocalJWKSet(jwks) {
108
- const set = new LocalJWKSet(jwks);
72
+ const set = new LocalJWKSetImpl(jwks);
109
73
  const localJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);
110
- Object.defineProperties(localJWKSet, {
111
- jwks: {
112
- value: () => structuredClone(set.jwks()),
113
- enumerable: false,
114
- configurable: false,
115
- writable: false,
116
- },
74
+ Object.defineProperty(localJWKSet, 'jwks', {
75
+ value: () => structuredClone(set.jwks()),
117
76
  });
118
77
  return localJWKSet;
119
78
  }