Modules declare go 1.27.1 and the build images follow. go fix applied the
modernizers, and SHA3-256 now comes from the standard library's crypto/sha3;
omitzero is not applied, since it changes what the JSON says.
Co-authored-by: Hanzo Dev <[email protected]>
Drive every reachable error branch in identity, KEM, handshake, wire,
channel, dial, listen, zap integration. Coverage went 77.4% → 100.0%.
Refactors that came out of the audit:
* Convert chacha20poly1305.New into mustChaCha20: the only failure
mode is wrong-size key, which never happens with our 32-byte HKDF
output. The construction is now infallible by precondition.
* Drop the Sign() error return: ML-DSA-65 SignCtx with a valid
identity never errors. Sign is now (id) -> []byte. callers in
runInitiator / runResponder simplified.
* derive() drops the impossible io.ReadFull error branch — HKDF over
32-byte output is infallible.
* parseHandshakeResponse precheck guarantees the ct/encLen reads
cannot short-fail, so those error returns are elided.
* XWingEncapsulate / GenerateXWingKey drop curve25519.X25519 error
branches that only fire on wrong-length scalars (we always pass 32
bytes).
Defensive seams:
* parseTestableDSAPub (identity.go) wraps mldsa.PublicKeyFromBytes so
tests can drive the defensive parse-error path even though current
upstream cannot produce one.
* decapsulateMLKEM (kem.go) wraps ML-KEM Decapsulate similarly. Both
seams default to the real upstream call in production.
Coverage tests added (coverage_test.go, ~36 tests):
identity: GenerateIdentityFrom short-reader, Sign/Verify error paths,
ParseIdentityPublic size + ml-dsa + roundtrip, Equal
nil + mismatched DSA + mismatched X-Wing.
kem: ParseXWingPublicKey size, GenerateXWingKey nil + short reader,
XWingEncapsulate short reader, XWingDecapsulate size +
low-order ephemeral.
wire: writeFrame oversize + writer error + partial-fail,
readFrame header EOF + zero-length + max-length + body EOF.
handshake: parseHandshakeInit short reads + trailing garbage,
parseHandshakeResponse all 4 error paths,
splitRespIDPayload all 5 error paths,
runInitiator missing-config + write/read failures + bad
response (4 separate adversarial responses),
runResponder missing-config + read failure + write failure +
bad signature + low-order X-Wing peer pubkey.
channel: newConn happy path, mustChaCha20 panic on bad key,
Read/Write sequence-exhausted, multi-frame split,
corrupted-ciphertext, double close, deadline getters,
nonceFor edge cases.
dial/listen: missing-config, bogus addr, dial unreachable, accept
handshake fail + post-close, HandshakeTimeout > 0 path.
zap: DialZAP / ListenZAP happy path + missing-config + dial fail.
Wire format and KEM combiner output are unchanged. Cross-language
KAT (72df...fe4ed) still pins.