How Relayium encrypts your files end-to-end
Last updated: 2026-08-06
"Is Relayium secure?" is a fair question — every file-transfer tool claims to be private. This page walks through exactly how Relayium keeps files private, in plain language, so you can judge the claim instead of taking it on faith.
There are two different encryption schemes at work, because there are two different situations: sending a file live to someone who is online right now, and leaving a download link for someone to pick up later. Both keep the server locked out of your file, but they get there in different ways — and it's worth knowing which one applies when.
Live transfers: two devices agree on a secret the server never sees
When you send a file in realtime — both people online, browser to browser — Relayium starts by having each device generate a fresh key pair using X25519, the same elliptic-curve key exchange used across modern secure messaging (technically, libsodium's crypto_kx). Each device keeps its private key to itself and sends only its public key to the other side.
From those two public keys, each device independently computes the same shared secret — a process that works precisely because of how elliptic-curve key exchange is built, not because the secret was sent anywhere. That shared secret becomes an AES-256-GCM key that exists only inside the two browsers. Every chunk of the file is sealed with that key and a unique nonce before it ever leaves the sender's device, so anything crossing the network — including the signaling server that helped the two browsers find each other — sees only ciphertext.
- A new key pair is generated for every transfer — nothing is reused across sessions.
- The shared AES-256-GCM key is derived independently on each device; it is never transmitted anywhere, including to Relayium's own servers.
- Encryption happens at the application layer, on top of WebRTC's own transport security, so it holds even if that transport layer were ever compromised.
The 6-digit code that catches a dishonest server
What you need to do this comparison
- Both devices in front of you, or one other person who is at theirs right now.
- A channel that is not this transfer — a phone call, or the room you are both in. Pasting the code into the same chat you are worried about proves nothing.
- Ten seconds. That is the whole cost of the only check that catches a dishonest server.
There's a subtlety worth being honest about. WebRTC's own built-in encryption (DTLS) exchanges key fingerprints through the signaling server that introduces the two devices to each other. If that server were dishonest, it could in theory sit in the middle and swap in its own keys — a classic man-in-the-middle attack — without either browser immediately noticing.
Relayium closes that gap with a short verification code. Both devices derive the same 6-digit Short Authentication String (SAS) from their two public keys, and can display it on screen. Showing it and stopping to compare it is advanced verification, which is off by default — so a default transfer shows no code. Everything else described here still runs on every transfer: the fresh keys, the encryption, the commit-then-reveal handshake and the per-chunk authentication. What a default transfer does not get is this check itself — catching a swapped key, or a stranger on the other end, needs advanced verification turned on and the two people actually comparing the code out of band. If the codes match, the public keys weren't swapped: the signaling or relay server did not impersonate either endpoint or terminate the application-layer end-to-end encryption. This does not mean there was no server on the network path — cross-network ciphertext may still travel through TURN by design. But a plain 6-digit code is only about 20 bits, which in principle a well-positioned attacker could try to brute-force into matching after seeing both real keys. To prevent that, Relayium uses a commit-then-reveal handshake: each side first sends a hash committing to its key, and only reveals the real key after receiving the other side's commitment. That ordering means a malicious server has to commit to a fake key blind, before it has seen the real one — it cannot pick a colliding key after the fact, so the short code stays trustworthy.
Start a transfer between the two devices and wait for the verification code to appear on each screen.
https://relayium.com/Read one of them out loud, digit by digit, over the out-of-band channel — not by copying it into the app or into the same chat thread.
Compare all six digits. Partial agreement is disagreement.
Accept only if they match. If they differ, decline and find out which machine the other person is actually on before trying again.
On the CLI, make the comparison blocking rather than optional: --verify stops the transfer at that point and waits for you to confirm, so no bytes move until someone has actually looked.
relayium send --verify ./report.pdf
What a matching comparison proves, and what it does not
Two screens showing the same six digits means the certificate fingerprints the two ends pinned agree, so the rendezvous did not substitute an endpoint or impersonate either side. That is exactly the attack this section is about.
It authenticates the two endpoints. It does not prove anything about every network hop in between, and it proves nothing at all if nobody compares it — which is why --verify exists.
- For the strongest guarantee, turn on advanced verification, then read the code aloud over a call or compare it in person, not just by eye on two screens next to each other.
- If the two codes don't match, stop — treat it as a sign someone may be intercepting the connection.
Making sure what arrives is exactly what was sent
Encryption protects secrecy, but it doesn't automatically prove nothing got corrupted or tampered with along the way. Relayium checks that separately: each chunk carries its own AES-GCM authentication tag, so a modified chunk fails to decrypt outright. On top of that, as each file is sent, both sides compute a running SHA-256 hash over its plaintext contents; when the file finishes, the sender's hash is compared against the receiver's. If they match, what landed on disk is byte-for-byte what was sent — if they don't, the file is flagged rather than silently accepted.
Stored links: a different key, generated once, held only in the link
Realtime transfer needs both people online at the same time. When that's not possible, Relayium offers a stored download link instead — and this uses a genuinely different mechanism, worth not confusing with the realtime one above.
There's no key exchange here, because there's no second device to exchange with yet. Instead, your browser generates a single random AES-256-GCM key and uses it to encrypt the files before anything is uploaded. That key is never sent to the server at all — it's appended to the download link after a # character, in what's called the URL fragment, a part of the address that browsers deliberately never transmit to a server. The server ends up storing only ciphertext it has no way to decrypt, plus bookkeeping like the ciphertext's size and an expiry timestamp. Anyone who opens the full link — fragment included — can decrypt the file locally in their browser; anyone without it just sees an opaque blob on the server. That's the zero-knowledge part: the server holds the encrypted file without ever holding the means to read it.
- Creating a stored link requires the sender to sign in; opening one to download never does.
- Links can be set to expire after 1 hour, 1 day, 3 days, 7 days, or up to 14 days depending on your plan, or to burn after the first completed download.
- Treat the full link like the file itself — anyone who has it can decrypt it, so share it the way you'd share the file.
What the server can see — and what it can't
It's worth spelling out exactly where the server sits in all of this, because "end-to-end encrypted" is a claim that's easy to make and harder to make precisely. On the same network in realtime mode, the file itself never touches Relayium's servers at all — it streams directly between the two browsers. The signaling server's job is limited to relaying connection-setup messages (the technical SDP/ICE information WebRTC needs to establish a direct link) so the two devices can find each other; it never sees file contents, filenames, or keys.
Across networks — where restrictive NATs and firewalls often rule out a direct path — the encrypted stream runs over a TURN relay server. The relay only ever forwards ciphertext; it has no key and cannot decrypt what passes through it. What it does do is count the bytes it relays against the sending account's monthly relay allowance, purely for metering and abuse prevention — never inspecting what's inside.
When the comparison goes wrong
Three outcomes, and only the first is an emergency. Knowing which one you are looking at is most of the value.
What you see, what to check, what it means
- The two screens show different codes.
https://relayium.com/ # the two screens show different verification codesStop and do not send the file. Differing codes mean the two ends pinned different certificate fingerprints, so the far end is not the machine you think it is. Confirm out of band which device the other person is on, then start over. Re-running with --verify makes the transfer wait at that comparison instead of leaving it to your attention.
- No verification code has appeared.
https://relayium.com/ # no verification code on screen yetThe code is derived from a connection, so it exists once the two ends have connected. Before that there is nothing to compare, and a transfer that never connects is a different problem from one whose codes disagree.
- You compared the codes by pasting one into the chat you are already using.
relayium send --verify ./report.pdf # holds the transfer at the comparisonThat does not test what you wanted to test. If that channel is the thing you are worried about, an attacker who can change the transfer can change the pasted code too. Read it aloud, or use a channel with a different failure mode than the one you are checking.
Frequently asked questions
Can Relayium read my files?
No. In realtime mode, the encryption key is derived independently on both devices and never leaves them — Relayium's servers never see it or the file contents. For stored links, the key lives only in the URL fragment, which browsers never send to any server, so the server only ever holds ciphertext it cannot decrypt.
What does the server actually see?
In realtime mode on the same network, only the connection-setup information needed to introduce two devices to each other — never file bytes. Across networks the TURN relay does carry the bytes, but only as ciphertext it holds no key for. For stored links, it sees ciphertext plus bookkeeping like size and expiry time — never the plaintext, filenames, or the decryption key.
Is the TURN relay a weak point?
In the browser it carries every cross-network transfer by design, not only the ones where a direct path failed — but it only ever handles ciphertext, and it has no key, so it can't read what it's relaying. Relayium counts the bytes it relays against your account's monthly allowance, but never inspects their contents.
Is Relayium open source?
Yes. The protocol design and all client and server code are public on GitHub under the AGPL-3.0 license, so the cryptography described here can be independently audited rather than taken on trust.
What if the two verification codes on screen don't match?
Stop the transfer. Two different codes mean the two devices are not looking at the same connection — exactly what a substituted key or a man-in-the-middle would produce, rather than a benign glitch. (A failed commit-then-reveal handshake is a separate, earlier failure: it aborts the connection itself, before any code is shown.) Don't proceed until you understand why.
Curious what it looks like in practice? Turn on advanced verification before you start a new connection, so the code comparison and the confirmation steps are in place from the very beginning.
Try Relayium now