ehbp 0.1.6 → 0.2.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/README.md +5 -7
- package/dist/cjs/client.d.ts +3 -0
- package/dist/cjs/client.d.ts.map +1 -1
- package/dist/cjs/client.js +17 -3
- package/dist/cjs/client.js.map +1 -1
- package/dist/cjs/derive.d.ts.map +1 -1
- package/dist/cjs/derive.js +3 -3
- package/dist/cjs/derive.js.map +1 -1
- package/dist/cjs/identity.d.ts +26 -4
- package/dist/cjs/identity.d.ts.map +1 -1
- package/dist/cjs/identity.js +103 -73
- package/dist/cjs/identity.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +6 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/client.d.ts +3 -0
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +17 -3
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/derive.d.ts.map +1 -1
- package/dist/esm/derive.js +1 -1
- package/dist/esm/derive.js.map +1 -1
- package/dist/esm/identity.d.ts +26 -4
- package/dist/esm/identity.d.ts.map +1 -1
- package/dist/esm/identity.js +98 -72
- package/dist/esm/identity.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/test/client.test.js +2 -1
- package/dist/esm/test/client.test.js.map +1 -1
- package/dist/esm/test/derive.test.js +31 -17
- package/dist/esm/test/derive.test.js.map +1 -1
- package/dist/esm/test/identity.test.js +4 -4
- package/dist/esm/test/identity.test.js.map +1 -1
- package/dist/esm/test/security.test.js +2 -1
- package/dist/esm/test/security.test.js.map +1 -1
- package/dist/esm/test/session-recovery.test.d.ts +9 -0
- package/dist/esm/test/session-recovery.test.d.ts.map +1 -0
- package/dist/esm/test/session-recovery.test.js +419 -0
- package/dist/esm/test/session-recovery.test.js.map +1 -0
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security.test.js","sourceRoot":"","sources":["../../../src/test/security.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,
|
|
1
|
+
{"version":3,"file":"security.test.js","sourceRoot":"","sources":["../../../src/test/security.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Recovery Token Tests
|
|
3
|
+
*
|
|
4
|
+
* These tests verify that extractSessionRecoveryToken and decryptResponseWithToken
|
|
5
|
+
* produce correct results by running real HPKE key exchanges and AES-256-GCM
|
|
6
|
+
* encryption/decryption — no mocks on the crypto path.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=session-recovery.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-recovery.test.d.ts","sourceRoot":"","sources":["../../../src/test/session-recovery.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Recovery Token Tests
|
|
3
|
+
*
|
|
4
|
+
* These tests verify that extractSessionRecoveryToken and decryptResponseWithToken
|
|
5
|
+
* produce correct results by running real HPKE key exchanges and AES-256-GCM
|
|
6
|
+
* encryption/decryption — no mocks on the crypto path.
|
|
7
|
+
*/
|
|
8
|
+
import { describe, it } from 'node:test';
|
|
9
|
+
import assert from 'node:assert';
|
|
10
|
+
import { readFileSync } from 'node:fs';
|
|
11
|
+
import { resolve, dirname } from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
import { Identity, extractSessionRecoveryToken, decryptResponseWithToken, serializeSessionRecoveryToken, deserializeSessionRecoveryToken, } from '../index.js';
|
|
14
|
+
import { PROTOCOL } from '../protocol.js';
|
|
15
|
+
import { CipherSuite, KEM_DHKEM_X25519_HKDF_SHA256, KDF_HKDF_SHA256, AEAD_AES_256_GCM, } from 'hpke';
|
|
16
|
+
import { bytesToHex, decryptChunk, deriveResponseKeys, encryptChunk, hexToBytes, EXPORT_LABEL, EXPORT_LENGTH, HPKE_REQUEST_INFO, RESPONSE_NONCE_LENGTH, } from '../derive.js';
|
|
17
|
+
// Shared suite — all key generation and SetupRecipient use this instance so
|
|
18
|
+
// CryptoKey objects are never passed across CipherSuite instances.
|
|
19
|
+
const suite = new CipherSuite(KEM_DHKEM_X25519_HKDF_SHA256, KDF_HKDF_SHA256, AEAD_AES_256_GCM);
|
|
20
|
+
const infoBytes = new TextEncoder().encode(HPKE_REQUEST_INFO);
|
|
21
|
+
const exportLabelBytes = new TextEncoder().encode(EXPORT_LABEL);
|
|
22
|
+
/**
|
|
23
|
+
* Generate a key pair from the shared suite and return a public-key-only
|
|
24
|
+
* Identity (for encryptRequestWithContext) plus the raw private key (for
|
|
25
|
+
* server-side simulation via SetupRecipient on the same suite).
|
|
26
|
+
*/
|
|
27
|
+
async function generateTestKeys() {
|
|
28
|
+
const { publicKey, privateKey } = await suite.GenerateKeyPair(true);
|
|
29
|
+
const pubKeyBytes = new Uint8Array(await suite.SerializePublicKey(publicKey));
|
|
30
|
+
const identity = await Identity.fromPublicKeyHex(bytesToHex(pubKeyBytes));
|
|
31
|
+
return { identity, privateKey };
|
|
32
|
+
}
|
|
33
|
+
function encodeSingleChunk(payload) {
|
|
34
|
+
const chunkLength = new Uint8Array(4);
|
|
35
|
+
new DataView(chunkLength.buffer).setUint32(0, payload.byteLength, false);
|
|
36
|
+
const body = new Uint8Array(4 + payload.byteLength);
|
|
37
|
+
body.set(chunkLength, 0);
|
|
38
|
+
body.set(payload, 4);
|
|
39
|
+
return body;
|
|
40
|
+
}
|
|
41
|
+
function encodeMultipleChunks(payloads) {
|
|
42
|
+
let totalLength = 0;
|
|
43
|
+
for (const p of payloads)
|
|
44
|
+
totalLength += 4 + p.byteLength;
|
|
45
|
+
const body = new Uint8Array(totalLength);
|
|
46
|
+
let offset = 0;
|
|
47
|
+
for (const p of payloads) {
|
|
48
|
+
new DataView(body.buffer, offset, 4).setUint32(0, p.byteLength, false);
|
|
49
|
+
offset += 4;
|
|
50
|
+
body.set(p, offset);
|
|
51
|
+
offset += p.byteLength;
|
|
52
|
+
}
|
|
53
|
+
return body;
|
|
54
|
+
}
|
|
55
|
+
function toArrayBuffer(bytes) {
|
|
56
|
+
const copy = new Uint8Array(bytes.byteLength);
|
|
57
|
+
copy.set(bytes);
|
|
58
|
+
return copy.buffer;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Simulates what the server does: receives the encrypted request,
|
|
62
|
+
* decrypts it, then builds an encrypted response using the HPKE
|
|
63
|
+
* receiver context (matching the real protocol).
|
|
64
|
+
*/
|
|
65
|
+
async function buildEncryptedResponse(request, privateKey, responseText) {
|
|
66
|
+
const requestEncHex = request.headers.get(PROTOCOL.ENCAPSULATED_KEY_HEADER);
|
|
67
|
+
assert(requestEncHex, `Missing ${PROTOCOL.ENCAPSULATED_KEY_HEADER} header`);
|
|
68
|
+
const requestEnc = hexToBytes(requestEncHex);
|
|
69
|
+
const recipientContext = await suite.SetupRecipient(privateKey, requestEnc, { info: infoBytes });
|
|
70
|
+
// Decrypt the request body to prove the HPKE handshake works
|
|
71
|
+
const encryptedBody = new Uint8Array(await request.arrayBuffer());
|
|
72
|
+
const chunkLen = new DataView(encryptedBody.buffer, encryptedBody.byteOffset, 4).getUint32(0, false);
|
|
73
|
+
const ciphertext = encryptedBody.slice(4, 4 + chunkLen);
|
|
74
|
+
await recipientContext.Open(ciphertext);
|
|
75
|
+
const responseNonce = new Uint8Array(RESPONSE_NONCE_LENGTH);
|
|
76
|
+
crypto.getRandomValues(responseNonce);
|
|
77
|
+
const exportedSecret = await recipientContext.Export(exportLabelBytes, EXPORT_LENGTH);
|
|
78
|
+
const keyMaterial = await deriveResponseKeys(exportedSecret, requestEnc, responseNonce);
|
|
79
|
+
const responseCiphertext = await encryptChunk(keyMaterial, 0, new TextEncoder().encode(responseText));
|
|
80
|
+
return new Response(toArrayBuffer(encodeSingleChunk(responseCiphertext)), {
|
|
81
|
+
status: 200,
|
|
82
|
+
headers: {
|
|
83
|
+
[PROTOCOL.RESPONSE_NONCE_HEADER]: bytesToHex(responseNonce),
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Builds a multi-chunk encrypted streaming response (simulating SSE).
|
|
89
|
+
*/
|
|
90
|
+
async function buildStreamingEncryptedResponse(request, privateKey, chunks) {
|
|
91
|
+
const requestEncHex = request.headers.get(PROTOCOL.ENCAPSULATED_KEY_HEADER);
|
|
92
|
+
assert(requestEncHex);
|
|
93
|
+
const requestEnc = hexToBytes(requestEncHex);
|
|
94
|
+
const recipientContext = await suite.SetupRecipient(privateKey, requestEnc, { info: infoBytes });
|
|
95
|
+
// Decrypt request to advance the HPKE context
|
|
96
|
+
const encryptedBody = new Uint8Array(await request.arrayBuffer());
|
|
97
|
+
const chunkLen = new DataView(encryptedBody.buffer, encryptedBody.byteOffset, 4).getUint32(0, false);
|
|
98
|
+
await recipientContext.Open(encryptedBody.slice(4, 4 + chunkLen));
|
|
99
|
+
const responseNonce = new Uint8Array(RESPONSE_NONCE_LENGTH);
|
|
100
|
+
crypto.getRandomValues(responseNonce);
|
|
101
|
+
const exportedSecret = await recipientContext.Export(exportLabelBytes, EXPORT_LENGTH);
|
|
102
|
+
const keyMaterial = await deriveResponseKeys(exportedSecret, requestEnc, responseNonce);
|
|
103
|
+
const encryptedChunks = [];
|
|
104
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
105
|
+
encryptedChunks.push(await encryptChunk(keyMaterial, i, new TextEncoder().encode(chunks[i])));
|
|
106
|
+
}
|
|
107
|
+
return new Response(toArrayBuffer(encodeMultipleChunks(encryptedChunks)), {
|
|
108
|
+
status: 200,
|
|
109
|
+
headers: {
|
|
110
|
+
[PROTOCOL.RESPONSE_NONCE_HEADER]: bytesToHex(responseNonce),
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
describe('Session Recovery Token', () => {
|
|
115
|
+
describe('extractSessionRecoveryToken', () => {
|
|
116
|
+
it('should return a token with correct field sizes', async () => {
|
|
117
|
+
const { identity } = await generateTestKeys();
|
|
118
|
+
const request = new Request('https://server.test/api', {
|
|
119
|
+
method: 'POST',
|
|
120
|
+
body: 'test body',
|
|
121
|
+
});
|
|
122
|
+
const { context } = await identity.encryptRequestWithContext(request);
|
|
123
|
+
assert(context, 'context must not be null for a request with a body');
|
|
124
|
+
const token = await extractSessionRecoveryToken(context);
|
|
125
|
+
assert.strictEqual(token.exportedSecret.length, 32, 'exportedSecret must be 32 bytes');
|
|
126
|
+
assert.strictEqual(token.requestEnc.length, 32, 'requestEnc must be 32 bytes');
|
|
127
|
+
});
|
|
128
|
+
it('should return the same exported secret as SenderContext.Export', async () => {
|
|
129
|
+
const { identity } = await generateTestKeys();
|
|
130
|
+
const request = new Request('https://server.test/api', {
|
|
131
|
+
method: 'POST',
|
|
132
|
+
body: 'test body',
|
|
133
|
+
});
|
|
134
|
+
const { context } = await identity.encryptRequestWithContext(request);
|
|
135
|
+
assert(context);
|
|
136
|
+
// Export directly from the SenderContext for comparison
|
|
137
|
+
const directExport = new Uint8Array(await context.senderContext.Export(exportLabelBytes, EXPORT_LENGTH));
|
|
138
|
+
const token = await extractSessionRecoveryToken(context);
|
|
139
|
+
assert.deepStrictEqual(token.exportedSecret, directExport, 'Token exportedSecret must match direct SenderContext.Export result');
|
|
140
|
+
});
|
|
141
|
+
it('should return requestEnc matching the context', async () => {
|
|
142
|
+
const { identity } = await generateTestKeys();
|
|
143
|
+
const request = new Request('https://server.test/api', {
|
|
144
|
+
method: 'POST',
|
|
145
|
+
body: 'test body',
|
|
146
|
+
});
|
|
147
|
+
const { context } = await identity.encryptRequestWithContext(request);
|
|
148
|
+
assert(context);
|
|
149
|
+
const token = await extractSessionRecoveryToken(context);
|
|
150
|
+
assert.deepStrictEqual(token.requestEnc, context.requestEnc, 'Token requestEnc must match context.requestEnc');
|
|
151
|
+
});
|
|
152
|
+
it('should produce different tokens for different requests', async () => {
|
|
153
|
+
const { identity } = await generateTestKeys();
|
|
154
|
+
const req1 = new Request('https://server.test/api', { method: 'POST', body: 'request 1' });
|
|
155
|
+
const req2 = new Request('https://server.test/api', { method: 'POST', body: 'request 2' });
|
|
156
|
+
const { context: ctx1 } = await identity.encryptRequestWithContext(req1);
|
|
157
|
+
const { context: ctx2 } = await identity.encryptRequestWithContext(req2);
|
|
158
|
+
assert(ctx1 && ctx2);
|
|
159
|
+
const token1 = await extractSessionRecoveryToken(ctx1);
|
|
160
|
+
const token2 = await extractSessionRecoveryToken(ctx2);
|
|
161
|
+
// Each request creates a fresh HPKE context, so exported secrets differ
|
|
162
|
+
assert.notDeepStrictEqual(token1.exportedSecret, token2.exportedSecret, 'Different requests must produce different exported secrets');
|
|
163
|
+
assert.notDeepStrictEqual(token1.requestEnc, token2.requestEnc, 'Different requests must produce different requestEnc values');
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
describe('decryptResponseWithToken', () => {
|
|
167
|
+
it('should decrypt a single-chunk response', async () => {
|
|
168
|
+
const { identity, privateKey } = await generateTestKeys();
|
|
169
|
+
const request = new Request('https://server.test/api', {
|
|
170
|
+
method: 'POST',
|
|
171
|
+
body: 'hello',
|
|
172
|
+
});
|
|
173
|
+
const { request: encryptedRequest, context } = await identity.encryptRequestWithContext(request);
|
|
174
|
+
assert(context);
|
|
175
|
+
const token = await extractSessionRecoveryToken(context);
|
|
176
|
+
// Server builds an encrypted response using the real HPKE handshake
|
|
177
|
+
const encryptedResponse = await buildEncryptedResponse(encryptedRequest, privateKey, 'response from server');
|
|
178
|
+
const decrypted = await decryptResponseWithToken(encryptedResponse, token);
|
|
179
|
+
const text = await decrypted.text();
|
|
180
|
+
assert.strictEqual(text, 'response from server');
|
|
181
|
+
});
|
|
182
|
+
it('should decrypt a multi-chunk streaming response', async () => {
|
|
183
|
+
const { identity, privateKey } = await generateTestKeys();
|
|
184
|
+
const request = new Request('https://server.test/api', {
|
|
185
|
+
method: 'POST',
|
|
186
|
+
body: 'hello',
|
|
187
|
+
});
|
|
188
|
+
const { request: encryptedRequest, context } = await identity.encryptRequestWithContext(request);
|
|
189
|
+
assert(context);
|
|
190
|
+
const token = await extractSessionRecoveryToken(context);
|
|
191
|
+
const chunks = ['chunk-0:', 'chunk-1:', 'chunk-2:done'];
|
|
192
|
+
const encryptedResponse = await buildStreamingEncryptedResponse(encryptedRequest, privateKey, chunks);
|
|
193
|
+
const decrypted = await decryptResponseWithToken(encryptedResponse, token);
|
|
194
|
+
const text = await decrypted.text();
|
|
195
|
+
assert.strictEqual(text, chunks.join(''));
|
|
196
|
+
});
|
|
197
|
+
it('should preserve response status and headers', async () => {
|
|
198
|
+
const { identity, privateKey } = await generateTestKeys();
|
|
199
|
+
const request = new Request('https://server.test/api', {
|
|
200
|
+
method: 'POST',
|
|
201
|
+
body: 'hello',
|
|
202
|
+
});
|
|
203
|
+
const { request: encryptedRequest, context } = await identity.encryptRequestWithContext(request);
|
|
204
|
+
assert(context);
|
|
205
|
+
const token = await extractSessionRecoveryToken(context);
|
|
206
|
+
const encryptedResponse = await buildEncryptedResponse(encryptedRequest, privateKey, 'ok');
|
|
207
|
+
const decrypted = await decryptResponseWithToken(encryptedResponse, token);
|
|
208
|
+
assert.strictEqual(decrypted.status, 200);
|
|
209
|
+
assert(decrypted.headers.has(PROTOCOL.RESPONSE_NONCE_HEADER));
|
|
210
|
+
});
|
|
211
|
+
it('should return the response as-is when body is null', async () => {
|
|
212
|
+
const token = {
|
|
213
|
+
exportedSecret: new Uint8Array(32),
|
|
214
|
+
requestEnc: new Uint8Array(32),
|
|
215
|
+
};
|
|
216
|
+
const response = new Response(null, { status: 204 });
|
|
217
|
+
const result = await decryptResponseWithToken(response, token);
|
|
218
|
+
assert.strictEqual(result.status, 204);
|
|
219
|
+
assert.strictEqual(result.body, null);
|
|
220
|
+
});
|
|
221
|
+
it('should throw on missing response nonce header', async () => {
|
|
222
|
+
const token = {
|
|
223
|
+
exportedSecret: new Uint8Array(32),
|
|
224
|
+
requestEnc: new Uint8Array(32),
|
|
225
|
+
};
|
|
226
|
+
// Body present but no Ehbp-Response-Nonce header
|
|
227
|
+
const response = new Response('encrypted-data', { status: 200 });
|
|
228
|
+
await assert.rejects(() => decryptResponseWithToken(response, token), /Missing Ehbp-Response-Nonce header/);
|
|
229
|
+
});
|
|
230
|
+
it('should throw on invalid response nonce length', async () => {
|
|
231
|
+
const token = {
|
|
232
|
+
exportedSecret: new Uint8Array(32),
|
|
233
|
+
requestEnc: new Uint8Array(32),
|
|
234
|
+
};
|
|
235
|
+
// 12-byte nonce instead of required 32
|
|
236
|
+
const shortNonce = bytesToHex(new Uint8Array(12));
|
|
237
|
+
const response = new Response('encrypted-data', {
|
|
238
|
+
status: 200,
|
|
239
|
+
headers: { [PROTOCOL.RESPONSE_NONCE_HEADER]: shortNonce },
|
|
240
|
+
});
|
|
241
|
+
await assert.rejects(() => decryptResponseWithToken(response, token), /Invalid response nonce length/);
|
|
242
|
+
});
|
|
243
|
+
it('should fail decryption with a wrong token', async () => {
|
|
244
|
+
const { identity, privateKey } = await generateTestKeys();
|
|
245
|
+
const request = new Request('https://server.test/api', {
|
|
246
|
+
method: 'POST',
|
|
247
|
+
body: 'hello',
|
|
248
|
+
});
|
|
249
|
+
const { request: encryptedRequest, context } = await identity.encryptRequestWithContext(request);
|
|
250
|
+
assert(context);
|
|
251
|
+
const encryptedResponse = await buildEncryptedResponse(encryptedRequest, privateKey, 'secret');
|
|
252
|
+
// Forge a token with random bytes — decryption must fail
|
|
253
|
+
const badToken = {
|
|
254
|
+
exportedSecret: crypto.getRandomValues(new Uint8Array(32)),
|
|
255
|
+
requestEnc: crypto.getRandomValues(new Uint8Array(32)),
|
|
256
|
+
};
|
|
257
|
+
const decrypted = await decryptResponseWithToken(encryptedResponse, badToken);
|
|
258
|
+
// The stream-level decryption fails when you actually try to read
|
|
259
|
+
await assert.rejects(() => decrypted.text(), /Decryption failed/);
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
describe('decryptResponseWithContext delegates to token path', () => {
|
|
263
|
+
it('should produce identical plaintext via context path and token path', async () => {
|
|
264
|
+
const { identity, privateKey } = await generateTestKeys();
|
|
265
|
+
// We need two identical requests since Response bodies are consumed once.
|
|
266
|
+
// Instead, we build two responses from the same server-side state.
|
|
267
|
+
const request = new Request('https://server.test/api', {
|
|
268
|
+
method: 'POST',
|
|
269
|
+
body: 'payload',
|
|
270
|
+
});
|
|
271
|
+
const { request: encryptedRequest, context } = await identity.encryptRequestWithContext(request);
|
|
272
|
+
assert(context);
|
|
273
|
+
const token = await extractSessionRecoveryToken(context);
|
|
274
|
+
// Build one encrypted response for the token path
|
|
275
|
+
const responseForToken = await buildEncryptedResponse(encryptedRequest.clone(), privateKey, 'identical-response');
|
|
276
|
+
const decryptedViaToken = await decryptResponseWithToken(responseForToken, token);
|
|
277
|
+
const textViaToken = await decryptedViaToken.text();
|
|
278
|
+
assert.strictEqual(textViaToken, 'identical-response');
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
describe('token serialization round-trip (simulating localStorage)', () => {
|
|
282
|
+
it('should work after JSON serialization and deserialization', async () => {
|
|
283
|
+
const { identity, privateKey } = await generateTestKeys();
|
|
284
|
+
const request = new Request('https://server.test/api', {
|
|
285
|
+
method: 'POST',
|
|
286
|
+
body: 'test',
|
|
287
|
+
});
|
|
288
|
+
const { request: encryptedRequest, context } = await identity.encryptRequestWithContext(request);
|
|
289
|
+
assert(context);
|
|
290
|
+
const originalToken = await extractSessionRecoveryToken(context);
|
|
291
|
+
// Simulate localStorage: serialize to JSON and back using hex helpers
|
|
292
|
+
const serialized = serializeSessionRecoveryToken(originalToken);
|
|
293
|
+
// Verify the JSON contains hex strings
|
|
294
|
+
const raw = JSON.parse(serialized);
|
|
295
|
+
assert.strictEqual(raw.exportedSecret, bytesToHex(originalToken.exportedSecret));
|
|
296
|
+
assert.strictEqual(raw.requestEnc, bytesToHex(originalToken.requestEnc));
|
|
297
|
+
const restoredToken = deserializeSessionRecoveryToken(serialized);
|
|
298
|
+
// Decrypt with the deserialized token
|
|
299
|
+
const encryptedResponse = await buildEncryptedResponse(encryptedRequest, privateKey, 'recovered after tab close');
|
|
300
|
+
const decrypted = await decryptResponseWithToken(encryptedResponse, restoredToken);
|
|
301
|
+
const text = await decrypted.text();
|
|
302
|
+
assert.strictEqual(text, 'recovered after tab close');
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
describe('interoperability test vector', () => {
|
|
306
|
+
it('should deserialize the shared fixture and re-serialize to identical JSON', () => {
|
|
307
|
+
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
308
|
+
const vectorPath = resolve(thisDir, '../../../../test-vectors/session-recovery-token.json');
|
|
309
|
+
const vectorJSON = readFileSync(vectorPath, 'utf-8');
|
|
310
|
+
const token = deserializeSessionRecoveryToken(vectorJSON);
|
|
311
|
+
assert.strictEqual(token.exportedSecret.length, 32, 'exportedSecret must be 32 bytes');
|
|
312
|
+
assert.strictEqual(token.requestEnc.length, 32, 'requestEnc must be 32 bytes');
|
|
313
|
+
assert.strictEqual(bytesToHex(token.exportedSecret), 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2');
|
|
314
|
+
assert.strictEqual(bytesToHex(token.requestEnc), '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef');
|
|
315
|
+
// Re-serialize and verify identical JSON content
|
|
316
|
+
const reserialized = serializeSessionRecoveryToken(token);
|
|
317
|
+
assert.deepStrictEqual(JSON.parse(reserialized), JSON.parse(vectorJSON));
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
describe('response decryption interop vector', () => {
|
|
321
|
+
it('should decrypt the shared response-decryption fixture', async () => {
|
|
322
|
+
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
323
|
+
const vectorPath = resolve(thisDir, '../../../../test-vectors/response-decryption.json');
|
|
324
|
+
const vector = JSON.parse(readFileSync(vectorPath, 'utf-8'));
|
|
325
|
+
const token = {
|
|
326
|
+
exportedSecret: hexToBytes(vector.exportedSecret),
|
|
327
|
+
requestEnc: hexToBytes(vector.requestEnc),
|
|
328
|
+
};
|
|
329
|
+
const responseNonce = hexToBytes(vector.responseNonce);
|
|
330
|
+
const expectedPlaintext = hexToBytes(vector.plaintext);
|
|
331
|
+
const encryptedResponse = hexToBytes(vector.encryptedResponse);
|
|
332
|
+
const km = await deriveResponseKeys(token.exportedSecret, token.requestEnc, responseNonce);
|
|
333
|
+
// Parse chunked framing: LEN (4 bytes) || ciphertext
|
|
334
|
+
const chunkLen = (encryptedResponse[0] << 24) | (encryptedResponse[1] << 16) |
|
|
335
|
+
(encryptedResponse[2] << 8) | encryptedResponse[3];
|
|
336
|
+
const ciphertext = encryptedResponse.slice(4, 4 + chunkLen);
|
|
337
|
+
const decrypted = await decryptChunk(km, 0, ciphertext);
|
|
338
|
+
assert.deepStrictEqual(decrypted, expectedPlaintext);
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
describe('Transport.getSessionRecoveryToken', () => {
|
|
342
|
+
it('should throw before any request is made', async () => {
|
|
343
|
+
const { identity } = await generateTestKeys();
|
|
344
|
+
const { Transport } = await import('../client.js');
|
|
345
|
+
const transport = new Transport(identity, 'server.test');
|
|
346
|
+
assert.throws(() => transport.getSessionRecoveryToken(), /No session recovery token available/);
|
|
347
|
+
});
|
|
348
|
+
it('should return a working token after a request', async () => {
|
|
349
|
+
const { identity, privateKey } = await generateTestKeys();
|
|
350
|
+
const { Transport } = await import('../client.js');
|
|
351
|
+
const transport = new Transport(identity, 'server.test');
|
|
352
|
+
const originalFetch = globalThis.fetch;
|
|
353
|
+
globalThis.fetch = (async (input) => {
|
|
354
|
+
const request = input instanceof Request ? input : new Request(input);
|
|
355
|
+
return buildEncryptedResponse(request, privateKey, 'via-transport');
|
|
356
|
+
});
|
|
357
|
+
try {
|
|
358
|
+
const response = await transport.post('https://server.test/api', 'body');
|
|
359
|
+
const responseText = await response.text();
|
|
360
|
+
assert.strictEqual(responseText, 'via-transport');
|
|
361
|
+
// The token should now be available
|
|
362
|
+
const token = transport.getSessionRecoveryToken();
|
|
363
|
+
assert.strictEqual(token.exportedSecret.length, 32);
|
|
364
|
+
assert.strictEqual(token.requestEnc.length, 32);
|
|
365
|
+
}
|
|
366
|
+
finally {
|
|
367
|
+
globalThis.fetch = originalFetch;
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
it('should update the token on each new request', async () => {
|
|
371
|
+
const { identity, privateKey } = await generateTestKeys();
|
|
372
|
+
const { Transport } = await import('../client.js');
|
|
373
|
+
const transport = new Transport(identity, 'server.test');
|
|
374
|
+
const originalFetch = globalThis.fetch;
|
|
375
|
+
globalThis.fetch = (async (input) => {
|
|
376
|
+
const request = input instanceof Request ? input : new Request(input);
|
|
377
|
+
return buildEncryptedResponse(request, privateKey, 'ok');
|
|
378
|
+
});
|
|
379
|
+
try {
|
|
380
|
+
await transport.post('https://server.test/api', 'request-1');
|
|
381
|
+
const token1 = transport.getSessionRecoveryToken();
|
|
382
|
+
await transport.post('https://server.test/api', 'request-2');
|
|
383
|
+
const token2 = transport.getSessionRecoveryToken();
|
|
384
|
+
// Each request creates a fresh HPKE context
|
|
385
|
+
assert.notDeepStrictEqual(token1.exportedSecret, token2.exportedSecret, 'Tokens from different requests must have different exported secrets');
|
|
386
|
+
}
|
|
387
|
+
finally {
|
|
388
|
+
globalThis.fetch = originalFetch;
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
it('should clear the token for bodyless requests', async () => {
|
|
392
|
+
const { identity, privateKey } = await generateTestKeys();
|
|
393
|
+
const { Transport } = await import('../client.js');
|
|
394
|
+
const transport = new Transport(identity, 'server.test');
|
|
395
|
+
const originalFetch = globalThis.fetch;
|
|
396
|
+
globalThis.fetch = (async (input) => {
|
|
397
|
+
const request = input instanceof Request ? input : new Request(input);
|
|
398
|
+
const hasEncKey = request.headers.has(PROTOCOL.ENCAPSULATED_KEY_HEADER);
|
|
399
|
+
if (hasEncKey) {
|
|
400
|
+
return buildEncryptedResponse(request, privateKey, 'encrypted');
|
|
401
|
+
}
|
|
402
|
+
return new Response('plaintext');
|
|
403
|
+
});
|
|
404
|
+
try {
|
|
405
|
+
// POST with body — token should be set
|
|
406
|
+
await transport.post('https://server.test/api', 'body');
|
|
407
|
+
const tokenAfterPost = transport.getSessionRecoveryToken();
|
|
408
|
+
assert(tokenAfterPost, 'Token should exist after POST with body');
|
|
409
|
+
// GET without body — token should be cleared
|
|
410
|
+
await transport.get('https://server.test/api');
|
|
411
|
+
assert.throws(() => transport.getSessionRecoveryToken(), /No session recovery token available/, 'Token should be cleared after bodyless request');
|
|
412
|
+
}
|
|
413
|
+
finally {
|
|
414
|
+
globalThis.fetch = originalFetch;
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
//# sourceMappingURL=session-recovery.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-recovery.test.js","sourceRoot":"","sources":["../../../src/test/session-recovery.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,QAAQ,EACR,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,EAC7B,+BAA+B,GAChC,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EACL,WAAW,EACX,4BAA4B,EAC5B,eAAe,EACf,gBAAgB,GAEjB,MAAM,MAAM,CAAC;AACd,OAAO,EACL,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,cAAc,CAAC;AAEtB,4EAA4E;AAC5E,mEAAmE;AACnE,MAAM,KAAK,GAAG,IAAI,WAAW,CAC3B,4BAA4B,EAC5B,eAAe,EACf,gBAAgB,CACjB,CAAC;AAEF,MAAM,SAAS,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAC9D,MAAM,gBAAgB,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AAEhE;;;;GAIG;AACH,KAAK,UAAU,gBAAgB;IAC7B,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACpE,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC;IAC9E,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IAC1E,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;AAClC,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAmB;IAC5C,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IACtC,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAEzE,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACpD,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACzB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACrB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAsB;IAClD,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,WAAW,IAAI,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;IAE1D,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IACzC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACvE,MAAM,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACpB,MAAM,IAAI,CAAC,CAAC,UAAU,CAAC;IACzB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,KAAiB;IACtC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC9C,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChB,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,sBAAsB,CACnC,OAAgB,EAChB,UAAe,EACf,YAAoB;IAEpB,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC;IAC5E,MAAM,CAAC,aAAa,EAAE,WAAW,QAAQ,CAAC,uBAAuB,SAAS,CAAC,CAAC;IAC5E,MAAM,UAAU,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IAE7C,MAAM,gBAAgB,GAAG,MAAM,KAAK,CAAC,cAAc,CACjD,UAAU,EACV,UAAU,EACV,EAAE,IAAI,EAAE,SAAS,EAAE,CACpB,CAAC;IAEF,6DAA6D;IAC7D,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACrG,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC;IACxD,MAAM,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAExC,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,qBAAqB,CAAC,CAAC;IAC5D,MAAM,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;IAEtC,MAAM,cAAc,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;IACtF,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,cAAc,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;IAExF,MAAM,kBAAkB,GAAG,MAAM,YAAY,CAC3C,WAAW,EACX,CAAC,EACD,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CACvC,CAAC;IAEF,OAAO,IAAI,QAAQ,CAAC,aAAa,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,EAAE;QACxE,MAAM,EAAE,GAAG;QACX,OAAO,EAAE;YACP,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,UAAU,CAAC,aAAa,CAAC;SAC5D;KACF,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,+BAA+B,CAC5C,OAAgB,EAChB,UAAe,EACf,MAAgB;IAEhB,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC;IAC5E,MAAM,CAAC,aAAa,CAAC,CAAC;IACtB,MAAM,UAAU,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IAE7C,MAAM,gBAAgB,GAAG,MAAM,KAAK,CAAC,cAAc,CACjD,UAAU,EACV,UAAU,EACV,EAAE,IAAI,EAAE,SAAS,EAAE,CACpB,CAAC;IAEF,8CAA8C;IAC9C,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACrG,MAAM,gBAAgB,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;IAElE,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,qBAAqB,CAAC,CAAC;IAC5D,MAAM,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;IAEtC,MAAM,cAAc,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;IACtF,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,cAAc,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;IAExF,MAAM,eAAe,GAAiB,EAAE,CAAC;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,eAAe,CAAC,IAAI,CAClB,MAAM,YAAY,CAAC,WAAW,EAAE,CAAC,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CACxE,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,QAAQ,CAAC,aAAa,CAAC,oBAAoB,CAAC,eAAe,CAAC,CAAC,EAAE;QACxE,MAAM,EAAE,GAAG;QACX,OAAO,EAAE;YACP,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,UAAU,CAAC,aAAa,CAAC;SAC5D;KACF,CAAC,CAAC;AACL,CAAC;AAED,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC3C,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAC9C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,yBAAyB,EAAE;gBACrD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,WAAW;aAClB,CAAC,CAAC;YAEH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;YACtE,MAAM,CAAC,OAAO,EAAE,oDAAoD,CAAC,CAAC;YAEtE,MAAM,KAAK,GAAG,MAAM,2BAA2B,CAAC,OAAO,CAAC,CAAC;YAEzD,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,EAAE,iCAAiC,CAAC,CAAC;YACvF,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,EAAE,6BAA6B,CAAC,CAAC;QACjF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;YAC9E,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAC9C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,yBAAyB,EAAE;gBACrD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,WAAW;aAClB,CAAC,CAAC;YAEH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;YACtE,MAAM,CAAC,OAAO,CAAC,CAAC;YAEhB,wDAAwD;YACxD,MAAM,YAAY,GAAG,IAAI,UAAU,CACjC,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,gBAAgB,EAAE,aAAa,CAAC,CACpE,CAAC;YAEF,MAAM,KAAK,GAAG,MAAM,2BAA2B,CAAC,OAAO,CAAC,CAAC;YAEzD,MAAM,CAAC,eAAe,CACpB,KAAK,CAAC,cAAc,EACpB,YAAY,EACZ,oEAAoE,CACrE,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAC9C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,yBAAyB,EAAE;gBACrD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,WAAW;aAClB,CAAC,CAAC;YAEH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;YACtE,MAAM,CAAC,OAAO,CAAC,CAAC;YAEhB,MAAM,KAAK,GAAG,MAAM,2BAA2B,CAAC,OAAO,CAAC,CAAC;YAEzD,MAAM,CAAC,eAAe,CACpB,KAAK,CAAC,UAAU,EAChB,OAAO,CAAC,UAAU,EAClB,gDAAgD,CACjD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;YACtE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAE9C,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,yBAAyB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;YAC3F,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,yBAAyB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;YAE3F,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,QAAQ,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC;YACzE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,QAAQ,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC;YACzE,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;YAErB,MAAM,MAAM,GAAG,MAAM,2BAA2B,CAAC,IAAI,CAAC,CAAC;YACvD,MAAM,MAAM,GAAG,MAAM,2BAA2B,CAAC,IAAI,CAAC,CAAC;YAEvD,wEAAwE;YACxE,MAAM,CAAC,kBAAkB,CACvB,MAAM,CAAC,cAAc,EACrB,MAAM,CAAC,cAAc,EACrB,4DAA4D,CAC7D,CAAC;YACF,MAAM,CAAC,kBAAkB,CACvB,MAAM,CAAC,UAAU,EACjB,MAAM,CAAC,UAAU,EACjB,6DAA6D,CAC9D,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;QACxC,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAC1D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,yBAAyB,EAAE;gBACrD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,OAAO;aACd,CAAC,CAAC;YAEH,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,GAC1C,MAAM,QAAQ,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;YACpD,MAAM,CAAC,OAAO,CAAC,CAAC;YAEhB,MAAM,KAAK,GAAG,MAAM,2BAA2B,CAAC,OAAO,CAAC,CAAC;YAEzD,oEAAoE;YACpE,MAAM,iBAAiB,GAAG,MAAM,sBAAsB,CACpD,gBAAgB,EAChB,UAAU,EACV,sBAAsB,CACvB,CAAC;YAEF,MAAM,SAAS,GAAG,MAAM,wBAAwB,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;YAC3E,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;YAEpC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;YAC/D,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAC1D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,yBAAyB,EAAE;gBACrD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,OAAO;aACd,CAAC,CAAC;YAEH,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,GAC1C,MAAM,QAAQ,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;YACpD,MAAM,CAAC,OAAO,CAAC,CAAC;YAEhB,MAAM,KAAK,GAAG,MAAM,2BAA2B,CAAC,OAAO,CAAC,CAAC;YAEzD,MAAM,MAAM,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;YACxD,MAAM,iBAAiB,GAAG,MAAM,+BAA+B,CAC7D,gBAAgB,EAChB,UAAU,EACV,MAAM,CACP,CAAC;YAEF,MAAM,SAAS,GAAG,MAAM,wBAAwB,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;YAC3E,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;YAEpC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAC1D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,yBAAyB,EAAE;gBACrD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,OAAO;aACd,CAAC,CAAC;YAEH,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,GAC1C,MAAM,QAAQ,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;YACpD,MAAM,CAAC,OAAO,CAAC,CAAC;YAEhB,MAAM,KAAK,GAAG,MAAM,2BAA2B,CAAC,OAAO,CAAC,CAAC;YACzD,MAAM,iBAAiB,GAAG,MAAM,sBAAsB,CACpD,gBAAgB,EAChB,UAAU,EACV,IAAI,CACL,CAAC;YAEF,MAAM,SAAS,GAAG,MAAM,wBAAwB,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;YAE3E,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC1C,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,MAAM,KAAK,GAAyB;gBAClC,cAAc,EAAE,IAAI,UAAU,CAAC,EAAE,CAAC;gBAClC,UAAU,EAAE,IAAI,UAAU,CAAC,EAAE,CAAC;aAC/B,CAAC;YAEF,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YACrD,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAE/D,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACvC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,KAAK,GAAyB;gBAClC,cAAc,EAAE,IAAI,UAAU,CAAC,EAAE,CAAC;gBAClC,UAAU,EAAE,IAAI,UAAU,CAAC,EAAE,CAAC;aAC/B,CAAC;YAEF,iDAAiD;YACjD,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YAEjE,MAAM,MAAM,CAAC,OAAO,CAClB,GAAG,EAAE,CAAC,wBAAwB,CAAC,QAAQ,EAAE,KAAK,CAAC,EAC/C,oCAAoC,CACrC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,KAAK,GAAyB;gBAClC,cAAc,EAAE,IAAI,UAAU,CAAC,EAAE,CAAC;gBAClC,UAAU,EAAE,IAAI,UAAU,CAAC,EAAE,CAAC;aAC/B,CAAC;YAEF,uCAAuC;YACvC,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;YAClD,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,gBAAgB,EAAE;gBAC9C,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,UAAU,EAAE;aAC1D,CAAC,CAAC;YAEH,MAAM,MAAM,CAAC,OAAO,CAClB,GAAG,EAAE,CAAC,wBAAwB,CAAC,QAAQ,EAAE,KAAK,CAAC,EAC/C,+BAA+B,CAChC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAC1D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,yBAAyB,EAAE;gBACrD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,OAAO;aACd,CAAC,CAAC;YAEH,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,GAC1C,MAAM,QAAQ,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;YACpD,MAAM,CAAC,OAAO,CAAC,CAAC;YAEhB,MAAM,iBAAiB,GAAG,MAAM,sBAAsB,CACpD,gBAAgB,EAChB,UAAU,EACV,QAAQ,CACT,CAAC;YAEF,yDAAyD;YACzD,MAAM,QAAQ,GAAyB;gBACrC,cAAc,EAAE,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;gBAC1D,UAAU,EAAE,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;aACvD,CAAC;YAEF,MAAM,SAAS,GAAG,MAAM,wBAAwB,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;YAE9E,kEAAkE;YAClE,MAAM,MAAM,CAAC,OAAO,CAClB,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,EACtB,mBAAmB,CACpB,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAClE,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;YAClF,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAE1D,0EAA0E;YAC1E,mEAAmE;YACnE,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,yBAAyB,EAAE;gBACrD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,SAAS;aAChB,CAAC,CAAC;YAEH,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,GAC1C,MAAM,QAAQ,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;YACpD,MAAM,CAAC,OAAO,CAAC,CAAC;YAEhB,MAAM,KAAK,GAAG,MAAM,2BAA2B,CAAC,OAAO,CAAC,CAAC;YAEzD,kDAAkD;YAClD,MAAM,gBAAgB,GAAG,MAAM,sBAAsB,CACnD,gBAAgB,CAAC,KAAK,EAAE,EACxB,UAAU,EACV,oBAAoB,CACrB,CAAC;YAEF,MAAM,iBAAiB,GAAG,MAAM,wBAAwB,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;YAClF,MAAM,YAAY,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,CAAC;YAEpD,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,0DAA0D,EAAE,GAAG,EAAE;QACxE,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;YACxE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAC1D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,yBAAyB,EAAE;gBACrD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,MAAM;aACb,CAAC,CAAC;YAEH,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,GAC1C,MAAM,QAAQ,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;YACpD,MAAM,CAAC,OAAO,CAAC,CAAC;YAEhB,MAAM,aAAa,GAAG,MAAM,2BAA2B,CAAC,OAAO,CAAC,CAAC;YAEjE,sEAAsE;YACtE,MAAM,UAAU,GAAG,6BAA6B,CAAC,aAAa,CAAC,CAAC;YAEhE,uCAAuC;YACvC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACnC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC;YACjF,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;YAEzE,MAAM,aAAa,GAAG,+BAA+B,CAAC,UAAU,CAAC,CAAC;YAElE,sCAAsC;YACtC,MAAM,iBAAiB,GAAG,MAAM,sBAAsB,CACpD,gBAAgB,EAChB,UAAU,EACV,2BAA2B,CAC5B,CAAC;YAEF,MAAM,SAAS,GAAG,MAAM,wBAAwB,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;YACnF,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;YAEpC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC5C,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;YAClF,MAAM,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACxD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,EAAE,sDAAsD,CAAC,CAAC;YAC5F,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAErD,MAAM,KAAK,GAAG,+BAA+B,CAAC,UAAU,CAAC,CAAC;YAE1D,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,EAAE,iCAAiC,CAAC,CAAC;YACvF,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,EAAE,6BAA6B,CAAC,CAAC;YAE/E,MAAM,CAAC,WAAW,CAChB,UAAU,CAAC,KAAK,CAAC,cAAc,CAAC,EAChC,kEAAkE,CACnE,CAAC;YACF,MAAM,CAAC,WAAW,CAChB,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,EAC5B,kEAAkE,CACnE,CAAC;YAEF,iDAAiD;YACjD,MAAM,YAAY,GAAG,6BAA6B,CAAC,KAAK,CAAC,CAAC;YAC1D,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAClD,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;YACrE,MAAM,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACxD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,EAAE,mDAAmD,CAAC,CAAC;YACzF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAE7D,MAAM,KAAK,GAAyB;gBAClC,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC;gBACjD,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC;aAC1C,CAAC;YAEF,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YACvD,MAAM,iBAAiB,GAAG,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACvD,MAAM,iBAAiB,GAAG,UAAU,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;YAE/D,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;YAE3F,qDAAqD;YACrD,MAAM,QAAQ,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC3D,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;YACpE,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC;YAE5D,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,EAAE,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YACxD,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;QACjD,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAC9C,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;YACnD,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;YAEzD,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,SAAS,CAAC,uBAAuB,EAAE,EACzC,qCAAqC,CACtC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAC1D,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;YACnD,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;YAEzD,MAAM,aAAa,GAAG,UAAU,CAAC,KAAK,CAAC;YAEvC,UAAU,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,KAAwB,EAAqB,EAAE;gBACxE,MAAM,OAAO,GAAG,KAAK,YAAY,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;gBACtE,OAAO,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;YACtE,CAAC,CAAiB,CAAC;YAEnB,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,yBAAyB,EAAE,MAAM,CAAC,CAAC;gBACzE,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC3C,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;gBAElD,oCAAoC;gBACpC,MAAM,KAAK,GAAG,SAAS,CAAC,uBAAuB,EAAE,CAAC;gBAClD,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBACpD,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAClD,CAAC;oBAAS,CAAC;gBACT,UAAU,CAAC,KAAK,GAAG,aAAa,CAAC;YACnC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAC1D,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;YACnD,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;YAEzD,MAAM,aAAa,GAAG,UAAU,CAAC,KAAK,CAAC;YAEvC,UAAU,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,KAAwB,EAAqB,EAAE;gBACxE,MAAM,OAAO,GAAG,KAAK,YAAY,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;gBACtE,OAAO,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;YAC3D,CAAC,CAAiB,CAAC;YAEnB,IAAI,CAAC;gBACH,MAAM,SAAS,CAAC,IAAI,CAAC,yBAAyB,EAAE,WAAW,CAAC,CAAC;gBAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,uBAAuB,EAAE,CAAC;gBAEnD,MAAM,SAAS,CAAC,IAAI,CAAC,yBAAyB,EAAE,WAAW,CAAC,CAAC;gBAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,uBAAuB,EAAE,CAAC;gBAEnD,4CAA4C;gBAC5C,MAAM,CAAC,kBAAkB,CACvB,MAAM,CAAC,cAAc,EACrB,MAAM,CAAC,cAAc,EACrB,qEAAqE,CACtE,CAAC;YACJ,CAAC;oBAAS,CAAC;gBACT,UAAU,CAAC,KAAK,GAAG,aAAa,CAAC;YACnC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;YAC5D,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAC1D,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;YACnD,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;YAEzD,MAAM,aAAa,GAAG,UAAU,CAAC,KAAK,CAAC;YAEvC,UAAU,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,KAAwB,EAAqB,EAAE;gBACxE,MAAM,OAAO,GAAG,KAAK,YAAY,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;gBACtE,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC;gBACxE,IAAI,SAAS,EAAE,CAAC;oBACd,OAAO,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;gBAClE,CAAC;gBACD,OAAO,IAAI,QAAQ,CAAC,WAAW,CAAC,CAAC;YACnC,CAAC,CAAiB,CAAC;YAEnB,IAAI,CAAC;gBACH,uCAAuC;gBACvC,MAAM,SAAS,CAAC,IAAI,CAAC,yBAAyB,EAAE,MAAM,CAAC,CAAC;gBACxD,MAAM,cAAc,GAAG,SAAS,CAAC,uBAAuB,EAAE,CAAC;gBAC3D,MAAM,CAAC,cAAc,EAAE,yCAAyC,CAAC,CAAC;gBAElE,6CAA6C;gBAC7C,MAAM,SAAS,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;gBAC/C,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,SAAS,CAAC,uBAAuB,EAAE,EACzC,qCAAqC,EACrC,gDAAgD,CACjD,CAAC;YACJ,CAAC;oBAAS,CAAC;gBACT,UAAU,CAAC,KAAK,GAAG,aAAa,CAAC;YACnC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ehbp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "JavaScript client for Encrypted HTTP Body Protocol (EHBP)",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"license": "MIT",
|
|
40
40
|
"dependencies": {
|
|
41
|
+
"@panva/hpke-noble": "^1.0.3",
|
|
41
42
|
"hpke": "^1.0.1"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|