From 4d0fb9b81b28d0c579ad0258225ee02ba4ea874f Mon Sep 17 00:00:00 2001 From: 3cL1p5e7 <3cL1p5e7@gmail.com> Date: Sun, 27 Feb 2022 13:05:05 +0300 Subject: [PATCH 1/2] service-worker: added certified_chunks support --- .../service-worker/src/sw/http_request.ts | 16 ++++++++++++- .../service-worker/src/sw/validation.ts | 23 ++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/typescript/service-worker/src/sw/http_request.ts b/typescript/service-worker/src/sw/http_request.ts index 3d972af8708..aab68150ab9 100644 --- a/typescript/service-worker/src/sw/http_request.ts +++ b/typescript/service-worker/src/sw/http_request.ts @@ -230,7 +230,7 @@ export async function handleRequest(request: Request): Promise { if (maybeCanisterId) { try { const replicaUrl = new URL(url.origin); - const agent = new HttpAgent({ host: replicaUrl.toString() }); + const agent = new HttpAgent({ host: replicaUrl.toString(), fetch: self.fetch.bind(self) }); const actor = Actor.createActor(canisterIdlFactory, { agent, canisterId: maybeCanisterId, @@ -256,6 +256,8 @@ export async function handleRequest(request: Request): Promise { let certificate: ArrayBuffer | undefined; let tree: ArrayBuffer | undefined; let encoding = ''; + let chunk_tree: ArrayBuffer | undefined; + let chunk_index = 0; for (const [key, value] of httpResponse.headers) { switch (key.trim().toLowerCase()) { case 'ic-certificate': @@ -263,12 +265,19 @@ export async function handleRequest(request: Request): Promise { const fields = value.split(/,/); for (const f of fields) { const [_0, name, b64Value] = [...f.match(/^(.*)=:(.*):$/)].map(x => x.trim()); + if (name === 'chunk_index') { + chunk_index = parseInt(b64Value); + continue; + } + const value = base64Arraybuffer.decode(b64Value); if (name === 'certificate') { certificate = value; } else if (name === 'tree') { tree = value; + } else if (name === 'chunk_tree') { + chunk_tree = value; } } } @@ -293,6 +302,8 @@ export async function handleRequest(request: Request): Promise { body.buffer, certificate, tree, + chunk_tree, + chunk_index, agent, shouldFetchRootKey, ); @@ -306,12 +317,15 @@ export async function handleRequest(request: Request): Promise { identity.buffer, certificate, tree, + chunk_tree, + chunk_index, agent, isLocal, ); } } if (bodyValid) { + console.log('Body valid', {httpRequest, httpResponse, headers}); return new Response(identity.buffer, { status: httpResponse.status_code, headers, diff --git a/typescript/service-worker/src/sw/validation.ts b/typescript/service-worker/src/sw/validation.ts index 62d07b8ca0a..46ffc18a7a3 100644 --- a/typescript/service-worker/src/sw/validation.ts +++ b/typescript/service-worker/src/sw/validation.ts @@ -25,6 +25,8 @@ export async function validateBody( body: ArrayBuffer, certificate: ArrayBuffer, tree: ArrayBuffer, + chunk_tree: ArrayBuffer | undefined, + chunk_index: number, agent: HttpAgent, shouldFetchRootKey = false, ): Promise { @@ -70,7 +72,26 @@ export async function validateBody( return false; } - return !!treeSha && equal(sha, treeSha); + if (!chunk_tree) { + return !!treeSha && equal(sha, treeSha); // backward compatibility + } + + const hashChunkTree: HashTree = cbor.decode(new Uint8Array(chunk_tree)); + const chunkWitnessHash = lookup_path([chunk_index.toString()], hashChunkTree); + + if (!chunkWitnessHash) { + console.error(`Unable to lookup index path of chunk witness index=${chunk_index}`); + return false; + } + + if (!equal(sha, chunkWitnessHash)) { + console.error(`Body hash does not equal witness chunk hash index=${chunk_index}`); + return false; + } + + const reconstructedTreeSha = await reconstruct(hashChunkTree); + + return equal(reconstructedTreeSha, treeSha); } function equal(buf1: ArrayBuffer, buf2: ArrayBuffer): boolean { From 2f73f2976eeafc3cff41dd35c3877d53bc22df3b Mon Sep 17 00:00:00 2001 From: 3cL1p5e7 <3cL1p5e7@gmail.com> Date: Sun, 27 Feb 2022 23:40:31 +0300 Subject: [PATCH 2/2] cleanup --- typescript/service-worker/src/sw/http_request.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/typescript/service-worker/src/sw/http_request.ts b/typescript/service-worker/src/sw/http_request.ts index aab68150ab9..a5a830ff300 100644 --- a/typescript/service-worker/src/sw/http_request.ts +++ b/typescript/service-worker/src/sw/http_request.ts @@ -325,7 +325,6 @@ export async function handleRequest(request: Request): Promise { } } if (bodyValid) { - console.log('Body valid', {httpRequest, httpResponse, headers}); return new Response(identity.buffer, { status: httpResponse.status_code, headers,