Relayium

Security & Threat Model

Last updated: 2026-08-02

Relayium is built so that the people transferring files or temporary text — not the server — hold the keys. This page describes exactly what is protected, how it works, and the limits of that protection.

The short version: on the same network, realtime files and messages move directly between devices; across networks, browser sessions use a relay that carries only end-to-end encrypted ciphertext and holds no content key. Fresh session keys are always used; an optional out-of-band verification code lets the two people also detect signaling interception. The detail follows.

Browser realtime file encryption (X25519 + AES-256-GCM)

For realtime file transfers in the browser, each transfer generates a fresh, ephemeral X25519 key pair on each device. The two browsers perform a key exchange to derive a shared AES-256-GCM key. Every file chunk is encrypted under that key with a unique nonce, so the signaling server — and any relay — sees ciphertext rather than file plaintext. CLI transfers use a different direct TLS 1.3 protocol described below.

The verification code (SAS) — detecting a malicious server

WebRTC's built-in encryption (DTLS) exchanges key fingerprints through the signaling server, so a dishonest server could sit in the middle and swap keys. To catch this, Relayium derives a 6-digit Short Authentication String (SAS) from both sides' public keys and can show it on both screens. Matching codes provide the strongest interception check only when the two people compare them out of band. Showing that code and stopping to compare it is a preference — “advanced verification”, off by default, and `--verify` in the CLI. Turning it off changes what is displayed and which steps pause for confirmation; it does not change the encryption. The commit-then-reveal handshake below still runs on every connection and still refuses one whose reveal does not match, keys are still generated on your device and never sent to us, the relay still carries only ciphertext, and in the browser, receiving files still asks you before anything is saved — the native macOS app writes into its configured destination (Downloads by default) instead of asking. That prompt is about unsolicited writes to your disk, not about who is on the other end; only comparing the code establishes that.

A plain 6-digit code (about 20 bits) could in principle be brute-forced by a relay racing to force a matching code. Relayium closes that gap with a commit-then-reveal handshake: each side first commits to its key by sending a hash, and only reveals the key after receiving the other side's commitment. CLI transfers use a separate SAS derived through a commit-then-reveal exchange of the pinned TLS certificate fingerprints; it too detects nothing unless someone actually compares it out of band, which is what `--verify` stops for.

Plaintext the server cannot see or decrypt

The service is designed so that our servers cannot see or decrypt the following plaintext:

In browser realtime mode on the same network, file and message bytes flow directly between the two devices. Across networks they pass through TURN as ciphertext, and the relay holds no content key. The signaling service still handles connection-setup data and can see metadata such as public IP addresses, room membership, timing, a chosen device nickname, and presence.

When browser files and text are relayed (TURN)

Browser file and text transfers across networks — pairing-code sessions, including their join links — run through a TURN server by design, not as a fallback. Restrictive NATs and firewalls make a genuinely direct path unlikely there, so the app forces the relay route outright. Same-network browser sessions receive no relay credentials and connect directly. CLI file and text transfers never use TURN: they are direct-only and fail if no direct path can be found.

Temporary text transfer

Browser text sessions use the Web protocol: the peers perform an ephemeral X25519 exchange and derive direction-separated AES-256-GCM subkeys in a domain separate from file-transfer keys. Each valid UTF-8 message is authenticated and encrypted as its own frame. Across networks, browser sessions use TURN by design; the relay carries ciphertext and has no message key. With advanced verification on, comparing the SAS out of band also detects signaling interception.

CLI text is a different, direct-only protocol over pinned TLS 1.3. It does not use the browser X25519/AES message framing or TURN, and it fails when no direct path can be established. Message bodies are not stored by Relayium, but either endpoint can copy, log, screenshot, or otherwise retain text after receiving it.

Stored download links — the key never leaves your browser

The optional download-link mode is for when the recipient is not online. Your browser encrypts the files with AES-256-GCM before anything is uploaded, and the decryption key is placed only in the URL fragment — the part after the # — which browsers never send to the server.

File integrity (SHA-256)

Beyond confidentiality, each file's integrity is verified. Every chunk carries an AES-GCM authentication tag, and a per-file SHA-256 hash is checked end-to-end on the receiving side, so a corrupted or tampered file is detected rather than silently accepted.

What Relayium does not protect against

End-to-end encryption protects data in transit between two honest endpoints. It cannot, by design, protect against:

Browser support and its limits

Relayium runs in any modern browser with WebRTC over HTTPS. A few capabilities differ by browser:

Open source and reporting issues

The protocol design and all client and server code are public on GitHub, so anyone can audit the cryptography, run their own server, or contribute. If you find a security issue, please report it privately through GitHub's vulnerability reporting on the repository, rather than opening a public issue.