## What does the project do?

Shade is a monorepo that implements secure messaging encryption between two parties (for example browser and server, or two clients). Messages are encrypted so the transport layer (HTTP, WebSocket, etc.) only sees opaque bytes — not the content.

Core idea: Embed `ShadeSessionManager` (from `@shade/core`) together with a `CryptoProvider` (e.g. Web Crypto in the browser/Bun) and storage. Then call `encrypt` / `decrypt` per peer, just like in the demo code `demo.ts`.

The first message to someone new performs key agreement (X3DH). After that each message uses the Double Ratchet: fresh message keys and periodic DH steps provide forward secrecy (past messages do not survive key compromise) and post-compromise security (the system “recovers” over time after a compromise).

## Packages (how they fit)

The protocol. X3DH, Double Ratchet, session shapes, errors. No platform crypto here — only the `CryptoProvider` interface.

- `ShadeSessionManager` — high-level API: `initialize`, `createPreKeyBundle`, `initSessionFromBundle`, `encrypt`, `decrypt`
- Symmetric encryption: AES-256-GCM with AAD from the ratchet header

Crypto implementation for web/Bun/Node via SubtleCrypto — X25519, Ed25519, HKDF, HMAC, random bytes.

- Lets you use `shade-core` in the browser and on servers that support Web Crypto
- Comments in source point toward future Android (e.g. Tink) as a separate provider

Binary wire format for messages: version + type + length-prefixed fields (big-endian).

- Type `0x01` = PreKeyMessage, `0x02` = RatchetMessage
- Use when you want to serialize `ShadeEnvelope` efficiently on the wire

Transport adapters — not encryption itself, but how you move bytes (e.g. fetch or WebSocket).

- Hooks your application to the channel you already use

Prekey server (Hono) — stores public keys so Alice can start a conversation while Bob is “offline”.

- `POST /v1/keys/register` — register identity + bundle
- `GET /v1/keys/bundle/:address` — fetch bundle (consumes one-time prekey when available)
- `POST /v1/keys/replenish` — replenish one-time prekeys

## Keys at a glance

Ed25519 signs the “signed prekey”. X25519 is used in Diffie–Hellman in X3DH and in the ratchet. One identity per device/user is typical.
An X25519 key that is published and signed by the identity. The recipient verifies the signature before DH. The codebase recommends rotation on the order of 1–7 days.
Optional but important for stronger security: each fetched bundle can include one one-time key that is removed after use (`processPreKeyMessage` clears it from storage). Improves protection against certain attacks when many clients connect to the same recipient.

## Interactive flow: zero to encrypted message

Click “Next step” to walk through the sequence as Shade builds it. This mirrors `ShadeSessionManager` and the demo in the repo.

### Sessions and messages

## X3DH and Double Ratchet (brief)

X3DH solves “I want to talk to Bob now, but Bob may not reply until later”. Bob publishes a prekey bundle on the server. Alice fetches it, runs 3 or 4 DH operations (depending on whether a one-time key is used), and derives a shared root key both parties can reconstruct — without the server learning the secret.

Double Ratchet uses that root as a starting point. For each message (or when new DH keys spin), keys are derived; on the wire payloads are AES-GCM with authentication (AAD binds ciphertext to the ratchet header). The protocol also tolerates messages arriving out of order within limits (`MAX_SKIP`).

Signal specifications (English): X3DH · Double Ratchet.

## Using Shade across projects

Treat Shade as three layers you combine as needed:

1. Core + crypto provider + storage — the E2EE engine itself (runs in a client or a server process that must decrypt).
2. Proto — when you want compact binary serialization.
3. Transport + prekey server — when you want standardized key discovery and channels.

Reference path: `bun demo.ts` from the repo root shows a frontend/backend flow with memory storage and real crypto primitives.