2c1e7f972dd9
fix: PCH-02-002 Noise XX message 1 empty-payload mixHash — wire change, ships with Android v2.3.0 (v4.0.0)
- time
- 2026-06-12 20:40 UTC · 4 months ago
- machine
- koh2
- agent
- gpt-5
- session
- pch-02 integration
- parent
- fc06218b9f63
↓ peach-browser-2c1e7f97.tar.gzatlas at this save
files changed3 files
src/shared/noise-blake2s-kat.test.ts+2 −2src/shared/noise-js.ts+5 −3src/shared/noise-xx.ts+6 −0src/shared/noise-blake2s-kat.test.ts+2 −2
@@ -101,9 +101,9 @@101101 102102 // Both directions agree (consistency) ...103103 expect(hex(a.handshakeHash)).toBe(hex(b.handshakeHash));104- // ... and equal the pinned BLAKE2s vector (a SHA-256 revert changes this).104+ // ... and equal the pinned BLAKE2s + canonical msg1-empty-hash vector.105105 expect(hex(a.handshakeHash)).toBe(106- "11c8bf7fcefad1f00ff8573c7bca66891626d053addae6d2b78b2f195a9ffd8a",106+ "505b6dcb59838e5d163f4fd4897cfff87c20ecca23aa993b416206aba25ee71c",107107 );108108 109109 // Transport keys are also BLAKE2s-derived; a frame must still round-trip.src/shared/noise-js.ts+5 −3
@@ -9,9 +9,11 @@99 * vectors only (a regression guard against accidental changes on the JS side).1010 *1111 * PCH-01-002: this implementation derives `h` and HKDF over BLAKE2s to match the12- * named pattern. A stock `snow` stack would interoperate; the Android port must13- * mirror the same hash choices. Any change to the hash, HKDF, or transcript here14- * is a BREAKING wire change and requires a coordinated Android release.12+ * named pattern. PCH-02-002 brought the XX hand-port back to the canonical13+ * empty-payload msg1 transcript too, so a stock Noise stack should interoperate.14+ * The Android port must mirror these hash choices and transcript steps. Any15+ * change to the hash, HKDF, or transcript here is a BREAKING wire change and16+ * requires a coordinated Android release.1517 */1618 1719 import { generateKeyPair, sharedKey } from "@stablelib/x25519";src/shared/noise-xx.ts+6 −0
@@ -93,6 +93,10 @@9393 // --- Message 1: -> e ---9494 const e = generateKeyPair();9595 h = mixHash(h, e.publicKey);96+ // PCH-02-002: canonical Noise still runs EncryptAndHash(empty) for msg1.97+ // No bytes are added to the wire; the transcript hash moves in lockstep with98+ // peach-android.99+ h = mixHash(h, new Uint8Array(0));96100 await send(e.publicKey);97101 98102 // --- Message 2: <- e, ee, s, es ---@@ -191,6 +195,8 @@191195 if (msg1.length < 32) throw new Error("Noise XX: msg1 too short");192196 const remoteEphemeral = msg1.slice(0, 32);193197 h = mixHash(h, remoteEphemeral);198+ // PCH-02-002: mirror the initiator's empty-payload MixHash for msg1.199+ h = mixHash(h, new Uint8Array(0));194200 195201 // --- Message 2: -> e, ee, s, es ---196202 const e = generateKeyPair();