1efabc88f7f7
L9/THREAT-008: extend Codex chunk integrity hash from 32 to 64 bits
- time
- 2026-05-16 05:23 UTC · 5 months ago
- machine
- koh2
- parent
- 5bbbd6642f42
↓ peach-browser-1efabc88.tar.gzatlas at this save
files changed5 files
src/popup/codex/codex.adversarial.test.ts+3 −3src/popup/codex/codex.test.ts+1 −1src/popup/codex/generate.test.ts+1 −1src/popup/codex/helpers.ts+2 −2src/shared/codex-types.ts+1 −1src/popup/codex/codex.adversarial.test.ts+3 −3
@@ -268,8 +268,8 @@268268 ]);269269 const tampered = { ...env, d: bytesToBase64Url(bytes) };270270 // The new data hash will almost certainly differ from env.h.271- const recomputed = (await sha256Hex(bytes)).slice(0, 8);272- if (recomputed === env.h) return; // 1-in-2^32 lottery; skip.271+ const recomputed = (await sha256Hex(bytes)).slice(0, 16);272+ if (recomputed === env.h) return; // 1-in-2^64 lottery; skip.273273 expect(await verifyChunkIntegrity(tampered)).toBe(false);274274 });275275 }@@ -426,7 +426,7 @@426426 // recomputed hash so the integrity check passes.427427 const evil = envs[0]!;428428 const fakeBytes = crypto.getRandomValues(new Uint8Array(CHUNK_SIZE));429- const fakeHash = (await sha256Hex(fakeBytes)).slice(0, 8);429+ const fakeHash = (await sha256Hex(fakeBytes)).slice(0, 16);430430 const fakeEnv: ChunkEnvelope = {431431 ...evil,432432 d: bytesToBase64Url(fakeBytes),src/popup/codex/codex.test.ts+1 −1
@@ -142,7 +142,7 @@142142 expect(envelope.c).toBe('PX-TEST-1234');143143 expect(envelope.d).toBeTruthy();144144 expect(envelope.h).toBeTruthy();145- expect(envelope.h.length).toBe(8);145+ expect(envelope.h.length).toBe(16);146146 });147147 148148 it('integrity check passes for valid envelope', async () => {src/popup/codex/generate.test.ts+1 −1
@@ -119,7 +119,7 @@119119 expect(env.t).toBe(7);120120 expect(env.p).toBe(false);121121 expect(env.c).toBe("PX-AAAA-BBBB");122- expect(env.h).toHaveLength(8);122+ expect(env.h).toHaveLength(16);123123 expect(await verifyChunkIntegrity(env)).toBe(true);124124 });125125 src/popup/codex/helpers.ts+2 −2
@@ -84,7 +84,7 @@8484 isParity: boolean,8585 verifyCode: string,8686 ): Promise<ChunkEnvelope> {87- const hash = (await sha256Hex(chunkBytes)).slice(0, 8);87+ const hash = (await sha256Hex(chunkBytes)).slice(0, 16);8888 return {8989 v: 2,9090 c: verifyCode,@@ -103,7 +103,7 @@103103 */104104 export async function verifyChunkIntegrity(envelope: ChunkEnvelope): Promise<boolean> {105105 const bytes = base64UrlToBytes(envelope.d);106- const expected = (await sha256Hex(bytes)).slice(0, 8);106+ const expected = (await sha256Hex(bytes)).slice(0, 16);107107 return expected === envelope.h;108108 }109109 src/shared/codex-types.ts+1 −1
@@ -57,7 +57,7 @@5757 p: boolean;5858 /** Chunk data, base64url-encoded. */5959 d: string;60- /** First 8 chars of SHA-256(rawChunkBytes), uppercase hex. Catches per-chunk corruption. */60+ /** First 16 chars (64 bits) of SHA-256(rawChunkBytes), hex. Catches per-chunk corruption with ≤2^-64 collision odds. */6161 h: string;6262 }6363