@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.
- package/bin/suveren-gateway.js +86 -5
- package/content/integrations/calendar.json +116 -22
- package/content/integrations/deploy-github.json +164 -0
- package/content/integrations/gmail.json +13 -4
- package/content/integrations/index.json +2 -1
- package/dist/control-plane/index.mjs +84 -7
- package/dist/mcp-server/http.mjs +147 -21
- package/dist/ui/assets/index-DecSrutK.js +105 -0
- package/dist/ui/index.html +1 -1
- package/node_modules/@hap/core/dist/index.d.mts +21 -0
- package/node_modules/@hap/core/dist/index.d.ts +21 -0
- package/node_modules/@hap/core/dist/index.js +17 -0
- package/node_modules/@hap/core/dist/index.mjs +17 -0
- package/node_modules/@hap/core/package.json +1 -1
- package/node_modules/@hap/core/src/gatekeeper.ts +28 -0
- package/node_modules/@hap/core/src/types.ts +21 -0
- package/node_modules/fast-uri/index.js +37 -1
- package/node_modules/fast-uri/package.json +1 -1
- package/node_modules/fast-uri/test/security.test.js +136 -0
- package/node_modules/hono/dist/cjs/helper/proxy/index.js +4 -0
- package/node_modules/hono/dist/cjs/jsx/base.js +1 -9
- package/node_modules/hono/dist/cjs/jsx/hooks/index.js +14 -11
- package/node_modules/hono/dist/cjs/middleware/cors/index.js +1 -1
- package/node_modules/hono/dist/cjs/middleware/language/language.js +10 -6
- package/node_modules/hono/dist/cjs/utils/cookie.js +2 -1
- package/node_modules/hono/dist/helper/proxy/index.js +4 -0
- package/node_modules/hono/dist/jsx/base.js +1 -9
- package/node_modules/hono/dist/jsx/hooks/index.js +14 -11
- package/node_modules/hono/dist/middleware/cors/index.js +1 -1
- package/node_modules/hono/dist/middleware/language/language.js +10 -6
- package/node_modules/hono/dist/utils/cookie.js +2 -1
- package/node_modules/hono/package.json +2 -3
- package/node_modules/ip-address/README.md +142 -128
- package/node_modules/ip-address/dist/common.d.ts +6 -0
- package/node_modules/ip-address/dist/common.js +17 -1
- package/node_modules/ip-address/dist/common.js.map +1 -1
- package/node_modules/ip-address/dist/ipv4.js +3 -12
- package/node_modules/ip-address/dist/ipv4.js.map +1 -1
- package/node_modules/ip-address/dist/ipv6.d.ts +9 -2
- package/node_modules/ip-address/dist/ipv6.js +35 -16
- package/node_modules/ip-address/dist/ipv6.js.map +1 -1
- package/node_modules/ip-address/package.json +5 -3
- package/node_modules/jose/README.md +13 -13
- package/node_modules/jose/dist/types/index.d.ts +6 -5
- package/node_modules/jose/dist/types/jwe/compact/decrypt.d.ts +17 -11
- package/node_modules/jose/dist/types/jwe/compact/encrypt.d.ts +7 -19
- package/node_modules/jose/dist/types/jwe/flattened/decrypt.d.ts +17 -11
- package/node_modules/jose/dist/types/jwe/flattened/encrypt.d.ts +7 -19
- package/node_modules/jose/dist/types/jwe/general/decrypt.d.ts +18 -13
- package/node_modules/jose/dist/types/jwe/general/encrypt.d.ts +20 -21
- package/node_modules/jose/dist/types/jwk/embedded.d.ts +8 -12
- package/node_modules/jose/dist/types/jwk/thumbprint.d.ts +0 -15
- package/node_modules/jose/dist/types/jwks/local.d.ts +12 -21
- package/node_modules/jose/dist/types/jwks/remote.d.ts +34 -165
- package/node_modules/jose/dist/types/jws/compact/sign.d.ts +2 -13
- package/node_modules/jose/dist/types/jws/compact/verify.d.ts +17 -13
- package/node_modules/jose/dist/types/jws/flattened/sign.d.ts +2 -13
- package/node_modules/jose/dist/types/jws/flattened/verify.d.ts +17 -13
- package/node_modules/jose/dist/types/jws/general/sign.d.ts +16 -17
- package/node_modules/jose/dist/types/jws/general/verify.d.ts +18 -15
- package/node_modules/jose/dist/types/jwt/decrypt.d.ts +17 -11
- package/node_modules/jose/dist/types/jwt/encrypt.d.ts +10 -34
- package/node_modules/jose/dist/types/jwt/sign.d.ts +2 -13
- package/node_modules/jose/dist/types/jwt/unsecured.d.ts +4 -13
- package/node_modules/jose/dist/types/jwt/verify.d.ts +14 -13
- package/node_modules/jose/dist/types/key/export.d.ts +0 -14
- package/node_modules/jose/dist/types/key/generate_key_pair.d.ts +7 -14
- package/node_modules/jose/dist/types/key/generate_secret.d.ts +16 -14
- package/node_modules/jose/dist/types/key/import.d.ts +18 -28
- package/node_modules/jose/dist/types/types.d.ts +239 -222
- package/node_modules/jose/dist/types/util/base64url.d.ts +11 -4
- package/node_modules/jose/dist/types/util/decode_jwt.d.ts +1 -9
- package/node_modules/jose/dist/types/util/decode_protected_header.d.ts +0 -8
- package/node_modules/jose/dist/types/util/errors.d.ts +128 -121
- package/node_modules/jose/dist/webapi/jwe/compact/decrypt.js +4 -22
- package/node_modules/jose/dist/webapi/jwe/flattened/decrypt.js +5 -153
- package/node_modules/jose/dist/webapi/jwe/flattened/encrypt.js +16 -111
- package/node_modules/jose/dist/webapi/jwe/general/decrypt.js +15 -3
- package/node_modules/jose/dist/webapi/jwe/general/encrypt.js +65 -81
- package/node_modules/jose/dist/webapi/jwk/embedded.js +5 -3
- package/node_modules/jose/dist/webapi/jwks/local.js +31 -72
- package/node_modules/jose/dist/webapi/jwks/remote.js +19 -28
- package/node_modules/jose/dist/webapi/jws/compact/sign.js +5 -2
- package/node_modules/jose/dist/webapi/jws/compact/verify.js +4 -16
- package/node_modules/jose/dist/webapi/jws/flattened/sign.js +7 -65
- package/node_modules/jose/dist/webapi/jws/flattened/verify.js +3 -89
- package/node_modules/jose/dist/webapi/jws/general/sign.js +19 -15
- package/node_modules/jose/dist/webapi/jws/general/verify.js +29 -9
- package/node_modules/jose/dist/webapi/jwt/decrypt.js +5 -5
- package/node_modules/jose/dist/webapi/jwt/sign.js +2 -3
- package/node_modules/jose/dist/webapi/jwt/unsecured.js +4 -3
- package/node_modules/jose/dist/webapi/jwt/verify.js +6 -6
- package/node_modules/jose/dist/webapi/key/export.js +37 -4
- package/node_modules/jose/dist/webapi/key/generate_key_pair.js +33 -82
- package/node_modules/jose/dist/webapi/key/import.js +8 -8
- package/node_modules/jose/dist/webapi/lib/asn1.js +53 -122
- package/node_modules/jose/dist/webapi/lib/buffer_utils.js +1 -0
- package/node_modules/jose/dist/webapi/lib/content_encryption.js +34 -109
- package/node_modules/jose/dist/webapi/lib/crypto_key.js +18 -126
- package/node_modules/jose/dist/webapi/lib/helpers.js +23 -0
- package/node_modules/jose/dist/webapi/lib/invalid_key_input.js +0 -1
- package/node_modules/jose/dist/webapi/lib/jwe_algorithms.js +116 -0
- package/node_modules/jose/dist/webapi/lib/jwe_decrypt.js +186 -0
- package/node_modules/jose/dist/webapi/lib/jwe_encrypt.js +110 -0
- package/node_modules/jose/dist/webapi/lib/jwk_to_key.js +8 -98
- package/node_modules/jose/dist/webapi/lib/jws_algorithms.js +76 -0
- package/node_modules/jose/dist/webapi/lib/jws_sign.js +74 -0
- package/node_modules/jose/dist/webapi/lib/jws_verify.js +107 -0
- package/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +68 -109
- package/node_modules/jose/dist/webapi/lib/key.js +132 -0
- package/node_modules/jose/dist/webapi/lib/key_algorithm.js +10 -0
- package/node_modules/jose/dist/webapi/lib/key_descriptor.js +7 -0
- package/node_modules/jose/dist/webapi/lib/key_management.js +162 -92
- package/node_modules/jose/dist/webapi/lib/options.js +48 -0
- package/node_modules/jose/dist/webapi/lib/signing.js +14 -56
- package/node_modules/jose/dist/webapi/lib/type_checks.js +13 -18
- package/node_modules/jose/dist/webapi/util/base64url.js +13 -4
- package/node_modules/jose/dist/webapi/util/decode_jwt.js +2 -2
- package/node_modules/jose/dist/webapi/util/decode_protected_header.js +5 -15
- package/node_modules/jose/dist/webapi/util/errors.js +1 -1
- package/node_modules/jose/package.json +2 -4
- package/package.json +2 -2
- package/profiles/deploy/0.6.profile.json +168 -0
- package/profiles/deploy/0.7.profile.json +168 -0
- package/profiles/email/0.4.profile.json +9 -2
- package/profiles/index.json +3 -1
- package/dist/ui/assets/index-Cog54HOo.js +0 -105
- package/node_modules/jose/dist/webapi/lib/aesgcmkw.js +0 -15
- package/node_modules/jose/dist/webapi/lib/aeskw.js +0 -25
- package/node_modules/jose/dist/webapi/lib/check_key_type.js +0 -122
- package/node_modules/jose/dist/webapi/lib/ecdhes.js +0 -52
- package/node_modules/jose/dist/webapi/lib/key_to_jwk.js +0 -34
- package/node_modules/jose/dist/webapi/lib/normalize_key.js +0 -166
- package/node_modules/jose/dist/webapi/lib/pbes2kw.js +0 -42
- package/node_modules/jose/dist/webapi/lib/rsaes.js +0 -24
- package/node_modules/jose/dist/webapi/lib/validate_algorithms.js +0 -10
- 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 {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
-
}
|
|
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 {
|
|
3
|
-
import {
|
|
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 {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
key;
|
|
16
|
-
options;
|
|
17
|
-
constructor(enc, key, options) {
|
|
13
|
+
state;
|
|
14
|
+
constructor(enc, key, crit) {
|
|
18
15
|
this.#parent = enc;
|
|
19
|
-
this.
|
|
20
|
-
this.options = options;
|
|
16
|
+
this.state = [undefined, undefined, key, crit];
|
|
21
17
|
}
|
|
22
18
|
setUnprotectedHeader(unprotectedHeader) {
|
|
23
|
-
assertNotSet(this.
|
|
24
|
-
this.
|
|
19
|
+
assertNotSet(this.state[0], 'setUnprotectedHeader');
|
|
20
|
+
this.state[0] = unprotectedHeader;
|
|
25
21
|
return this;
|
|
26
22
|
}
|
|
27
23
|
setKeyManagementParameters(parameters) {
|
|
28
|
-
assertNotSet(this.
|
|
29
|
-
this.
|
|
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,
|
|
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(
|
|
81
|
-
.
|
|
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
|
-
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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 =
|
|
131
|
+
enc = headers[2];
|
|
123
132
|
}
|
|
124
|
-
else if (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(
|
|
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
|
-
|
|
146
|
-
|
|
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
|
-
|
|
167
|
-
target.header = flattened.header;
|
|
154
|
+
copyOptionalMembers(flattened, jwe, target);
|
|
168
155
|
continue;
|
|
169
156
|
}
|
|
170
|
-
const alg =
|
|
171
|
-
|
|
172
|
-
|
|
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 (
|
|
178
|
-
target.header = { ...
|
|
161
|
+
if (unprotectedHeader || parameters)
|
|
162
|
+
target.header = { ...unprotectedHeader, ...parameters };
|
|
179
163
|
}
|
|
180
164
|
return jwe;
|
|
181
165
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
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
|
|
13
|
-
|
|
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 {
|
|
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
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
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
|
|
43
|
-
const candidates = this.#jwks.keys.filter((jwk) =>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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,
|
|
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,
|
|
57
|
+
return importWithAlgCache(this.#cached, jwk, entry);
|
|
94
58
|
}
|
|
95
59
|
}
|
|
96
|
-
async function importWithAlgCache(cache, jwk,
|
|
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
|
|
100
|
-
if (key
|
|
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
|
|
72
|
+
const set = new LocalJWKSetImpl(jwks);
|
|
109
73
|
const localJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);
|
|
110
|
-
Object.
|
|
111
|
-
|
|
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
|
}
|