04
Encrypting content
- The core creates a fresh 256-bit content key for each post or card. A post's photos, videos and files are encrypted under the same key.
- The body and the author's signature are padded to a size class and encrypted with XChaCha20-Poly1305. Post text is padded to 256 bytes, doubling up to 64 KiB, then to multiples of 64 KiB.
- The content key is sealed for each recipient and delivered through their pair mailbox (section 5). The server stores the ciphertext under a random id, with no author or recipient field. Chat lines are encrypted under the chat's secret instead (section 5).
Signatures
The identity key signs a domain tag, the item's kind and context (the post or chat it belongs to), the author's account number, the item id, a timestamp and the SHA-256 hash of the body. The signature sits inside the ciphertext, hidden from the server. Recipients show an item only if it verifies against a key they verified, and the bound kind and context prevent replay elsewhere.
Key envelopes
- Outer, 1,201 bytes for a 32-byte key: used wherever an envelope is stored on the server or travels on its own, such as Fam requests, invitation bundles, encrypted backups and reports. It uses the hybrid KEM in section 9.
- Inner, 104 bytes: used only inside a pair-mailbox note, which is already encrypted under the pair's 256-bit secret. It holds an ephemeral X25519 public key, a nonce, and the content key under XChaCha20-Poly1305, keyed by HKDF-SHA256 of the shared secret salted with both public keys.
Each opener accepts exactly one length, so an outer layer can't be downgraded to the inner format. Non-canonical and small-order X25519 keys and all-zero shared secrets are rejected.
Media and files
Photos are encrypted whole. Videos and files use 64 KiB chunks whose nonces include the chunk index and whose associated data covers the header and a final-chunk flag, so truncation, reordering, extension and splicing fail; nothing is written out until every chunk authenticates. Files sit under random names, need a secret (hashed on the server) for every action, and aren't linked to an account or a post.
Cards
A member's name, bio, photo and Backers form an encrypted card. Its key goes only to the member's Fam through pair mailboxes, unless the member chooses Everyone; then it is also wrapped with a member key that every member holds. The server knows which setting was chosen.