keykammer
Keykammer is a peer-to-peer encrypted chat program built around one idea: any arbitrary file is simultaneously the room ID and the encryption key. Two people holding the same file - a photo, a PDF, a binary, anything - can open the same private chatroom from across the internet. Without the file there’s no way to decrypt the messages, no way to join the room, and no way to know the room exists at all.
The word Kammer is German for “chamber”, as in a secret room. I’m not entirely sold on the name, but I can’t think of anything better. This is one of the more complex programs I’ve ever made, so there’s still a good amount of testing and tweaking to do. I created a website at www.keykammer.com. If that website is up, then the program is in a pretty good state.
The next step (after it’s fully functional) is turning this into a phone app. A simple messaging/chat GUI where you open/join a room by selecting a file. I imagine it won’t be too hard after the CLI/backend side is completely done.
Details
Here’s how it works:
Say Alice runs the program with a picture of her dog as the keyfile:
keykammer fluffy.jpg. The file is hashed to a room ID, and that same
file derives the key that encrypts every message. Her client asks a
discovery server whether that room exists yet; it doesn’t, so the room
is listed - meaning the server now holds exactly one fact, that this
room ID is at this address. Bob runs the program with the same file,
derives the same room ID, and the discovery server hands back Alice’s
address so his client can connect directly to her. Once the room
hits capacity (two users by default) the listing is deleted, so if
anyone else goes looking for the room there’s no evidence it existed.
The discovery server is optional anyway - you can bypass it with a
direct address, or run your own.
It’s written in Go, and the same binary is the chat server, the client, and the discovery server depending on the flags. Peers talk over gRPC; rooms live only in RAM, only while users are connected, and nothing is ever written to disk. Messages are encrypted before they leave the sender, so the discovery server only ever sees room IDs and addresses. There’s a terminal UI and UPnP port forwarding to get through home routers.
Room IDs are SHA-256; the encryption key comes from HKDF-SHA256 over
the file contents, and messages use AES-256-GCM. HKDF rather than
another hash because keyfile entropy varies so wildly - a JPEG and a
short text file are very different inputs - and HKDF is built to
produce uniformly random key material from uneven input. GCM because
it authenticates as well as encrypts, so tampering makes decryption
fail outright and there’s no separate MAC to get wrong. It’s all Go
standard library plus x/crypto/hkdf.
The obvious limitation is that there’s no forward secrecy - the key comes from the file, so it’s the same every session, and anyone who gets the file can read recorded past traffic. The file is the identity, which is the whole design, but it means keyfile hygiene is essentially the entire threat model.
The code and prebuilt binaries are here on GitHub. Again, it mostly works, but it isn’t finished - I’m not really used to all this networking… work.