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
5 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 −1
src/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),

view file

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 () => {

view file

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 

view file

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 

view file

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 

view file