Pin SHA3-256("\./X-Wing" || ssM || ssX || ctX || pkX) for the fixed
inputs ssM=0x01...x32, ssX=0x02...x32, ctX=0x03...x32, pkX=0x04...x32.
Expected hex:
72df2088314a73de80c21d9593f13fcd5629c800c70b1507f0dd918fde5fe4ed
Same KAT is duplicated in:
- ~/work/zap/zap/src/zwing.rs (Rust crate)
- ~/work/zap/zap-py/tests/test_zwing.py
- ~/work/zap/zap-js/tests/zwing.test.ts
If any language port diverges on label, hash, or input ordering, that
test fails first. Cross-implementation interop drift caught at compile
time, not in production.
Composing PQ transport with ZAP RPC was already a 2-line pattern:
raw, _ := zwing.Dial(ctx, addr, cfg)
conn := zap.NewConn(raw, nil)
Two lines means two ways to mess it up (forget to wrap, leak the
raw conn). Add the canonical one-call wrappers so there is exactly
one way to do it:
conn, _ := zwing.DialZAP(ctx, addr, cfg)
ln, _ := zwing.ListenZAP(":9999", cfg)
srv := zap.NewServer(ln, handler)
Pairs with luxfi/api v1.0.10 zap.NewListener. No new wire format,
no new dep — these are sugar over the existing primitives.
Z-Wing v0.1.0 briefly relabelled the X-Wing KDF combiner with a
"Z-Wing" domain separator. That was wrong: the only reason to use
IETF X-Wing is exact interop with anything that speaks the IETF
draft, and rebranding the combiner breaks that interop while adding
zero security. The Lux contribution lives ONE layer up.
This commit restores the IETF labels everywhere:
* kem.go: combineXWing writes "\./" || "X-Wing" || ss_M || ss_X ||
ct_X || pk_X. The label slice names go back to xwingLabelPrefix /
xwingLabelName.
* LLM.md: rewritten to position Z-Wing as a composition (real X-Wing
KEM + Ed25519+ML-DSA-65 hybrid identity + ChaCha20-Poly1305 +
RNS-or-TCP transport), not a separate KEM. Z-Wing's domain
separation lives in the HKDF info string "lux.zwing.v1/{i2r,r2i}"
and the ML-DSA context "lux.zwing.v1", not in the KEM.
Tests pass with the IETF labels (TestHandshakeRoundTrip,
TestZAPOverZWing, TestForwardSecrecy, TestSequencedNonces,
TestIdentityMismatch, TestDialListen).
The package is still called zwing and the construction is still
called Z-Wing. The KEM at the bottom of the stack is and stays IETF
X-Wing.