← Home

How it works.

Three layers between your words and everyone else.

The server never sees your messages, never sees your room link, and never stores anything readable. If someone seized the server, they'd get a pile of hashes and ciphertext. That's the point.

Your browser Encrypts messages
Holds the room secret
The server Routes ciphertext
Sees only hashes
Their browser Decrypts messages
Holds the room secret
1

The room secret stays in the URL

When you create a room, your browser generates a 256-bit random secret. This secret lives only in the URL fragment — the part after the hash. It never leaves your device or hits the server. Instead, your browser derives a one-way hash from it and sends only that hash to register the room.

Derivation: room_hash = SHA-256("hisohiso.room_hash" || room_secret). The server stores the hash, never the secret. Sharing the room means sharing the URL. Losing the URL means losing access — by design.

2

Messages are encrypted before they leave

Every message is encrypted in your browser using AES-256-GCM before it's sent. The encryption key is derived from the room secret, so only people who have the link can read anything. The server relays ciphertext — it can't decrypt a single word.

Key derivation: k_msg = HKDF(room_secret, "hisohiso.k_msg"). Each message gets a unique 12-byte nonce. The room hash, message type, and message ID are bound as additional authenticated data (AAD), so tampering is detectable.

3

The server proves it knows nothing

The server's database contains room hashes, participant token hashes, and timestamps. No names, no emails, no plaintext, no message history. Participants are identified by random tokens that are also stored as hashes. Even if someone dumped the entire database, they couldn't reconstruct who was in which room or what was said.

Participant tokens are 32-byte random values. The server stores SHA-256(token) and validates requests by hashing the presented token. Messages are never stored server-side — they're relayed in real time and discarded. History lives in IndexedDB on each device, nowhere else.

What about joining?

Someone with the link knocks. An existing participant — anyone already in the room — approves or rejects. If nobody is online, nobody can approve. There's no backdoor, no admin account, no way in without someone inside saying yes.

And any participant can disband the room entirely. When that happens, the server deletes the room record, all connections drop, and clients wipe local data for that room. Irreversible.

What we didn't build

No accounts. No password recovery. No email verification. No phone number binding. No cloud backup of messages. No read receipts. No typing indicators. No user profiles. No contact list. No friend requests.

Every feature we left out is a surface we don't have to secure and a promise we don't have to keep.

Open source

The code is on GitHub. Read it. Run your own. The protocol is documented in the repo. If you find a flaw, open an issue.