mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-08-15 07:06:11 +00:00
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>