ecgang 0a5647b3e8 Add golden test vectors for the courier wire format
The courier layer is only implementable from the Swift source today, and three
of the ways a second client gets it wrong fail silently — it builds, connects,
and delivers nothing, with no error at either end:

- `expiry` is milliseconds. Seconds makes every envelope read as long expired,
  so it is dropped at deposit with nothing logged.
- The signature does not cover the wire bytes. It covers a re-encoding with
  ttl zeroed, isRSR cleared and the signature omitted, which is then PKCS#7
  padded — a spray receipt is 46 bytes unsigned and unpadded, but 256 bytes
  signed. Signing the 46 produces a signature that never verifies.
- The signing key is Ed25519. CryptoKit spells it Curve25519.Signing, so
  reaching for a "Curve25519" primitive elsewhere yields X25519 key agreement.

Prose cannot defend against that class of bug; a fixture can. These vectors
pin the envelope TLV, the copies clamp, recipient-tag derivation, the
ciphertext hash, and the padded signing pre-image, and they are asserted from
the implementation so they cannot drift without a test failing.

Signature bytes are deliberately not pinned: CryptoKit's Ed25519 signing is
randomized rather than the deterministic RFC 8032 construction, so two
signatures over identical input differ and both verify. A second
implementation will not reproduce these bytes and does not need to — the
pre-image is what must match.

docs/courier-test-vectors.json carries the same values for implementers who
are not running Swift.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 14:47:50 -07:00
..