1# PCH-02-009 — Reject zero X25519 DH outputs in Noise XX and NK23**Severity:** Informational4**Target files:** `src/shared/noise-xx.ts` (6 DH sites),5`src/shared/noise-js.ts` (6 DH sites)6**Report:** peach-code-review.md, Finding PCH-02-00978## Implementation choice (simpler than the brief's sample)910`@stablelib/x25519`'s `sharedKey` already has the exact guard built in:11`sharedKey(mySecretKey, theirPublicKey, rejectZero = false)` — with12`rejectZero: true` it throws `"X25519: invalid shared key"` on an all-zero13output (verified in `node_modules/@stablelib/x25519/lib/x25519.js:606-624`).14Passing `true` at every call site is equivalent to the brief's manual15`every(b => b === 0)` check, applies to the raw 32-byte output before it16reaches `mixKey`/HMAC, and adds no new code path to maintain.1718**Not a wire change.** Honest peers never produce an all-zero shared secret19(the probability for random keys is negligible; only adversarially chosen20low-order/identity points do). Each side can adopt the check independently —21no Android coordination required, though mirroring it there is recommended.2223## Exact edits — all 12 DH call sites2425`noise-xx.ts` — add a rationale comment at the first site, `, true` at all six:2627```typescript282930 const ee = sharedKey(e.secretKey, remoteEphemeral);3132 33 34 35 const ee = sharedKey(e.secretKey, remoteEphemeral, true);36373839404142```4344`noise-js.ts` — same pattern, comment at the first site:4546```typescript4748495051525354```5556The two auth-proof sites (175, 362) key an HMAC rather than `mixKey`; the57same contributory-behaviour argument applies — a zero MAC key derived from an58attacker-chosen point should abort, not authenticate.5960## KAT / existing-test impact6162None. The pinned vectors (`noise-js.test.ts` self-vectors,63`noise-blake2s-kat.test.ts` cross-repo vectors) all use honest keys whose DH64outputs are non-zero; `rejectZero` only changes behaviour on the degenerate65inputs the new tests inject.6667## Tests6869`noise.reject-zero-dh.test.ts` (in this folder) — 5 tests: NK initiator70aborts against an all-zero (low-order) responder static; NK responder aborts71on an all-zero msg-1 ephemeral; XX responder aborts on an all-zero msg-172ephemeral; full NK and XX handshakes over an in-memory transport still73succeed with honest keys (regression).74Destination: `src/shared/noise.reject-zero-dh.test.ts`.7576## Save message (integration)7778`fix: PCH-02-009 reject zero X25519 DH output at all 12 Noise XX/NK call sites via stablelib rejectZero`