handover.tools

Security

Two modes, two different guarantees. One-shot trusts the server; channel doesn't have to.

Who can read it
One-shot: whoever has the link, and the server. Channel: only the two paired machines.
Stored as
One-shot: plaintext. Channel: ciphertext.
You need
One-shot: nothing; MCP, curl or a browser. Channel: a small local client on both machines.

One-shot not encrypted

The link
The whole code, the link's last 8 letters, goes to the server. It is one of 228, about 5×1010, and each caller gets 200 tries a day.
Lifetime
One fetch by default. Unreadable after 60 minutes, at most 24 hours.
Early delete
Only the conversation that sent it can revoke it; the revoke key lives only there. Whoever holds the link can't delete it.
Not protected
Anyone who can read our database while it is stored, including us.

Channel end-to-end encrypted

Pairing, in order:

  1. Machine A

    Makes up a 5-character password

    It never leaves machine A. The server only hands out a 3-character nameplate.

  2. You

    Give kvmtrhxp to machine B

    Nameplate and password together. Only the first 3 letters reach the server.

  3. Both machines

    Run SPAKE2 through the server

    Both end up with the same 256-bit key. The nameplate is used up.

  4. Machine B

    Sends an encrypted hello

    When machine A can open it, both ends are confirmed. After that every message is sealed with ChaCha20-Poly1305 and numbered by the sender.

What happens if

The database is copied
By a breach, a backup, or us: ciphertext and key hashes. No plaintext, no keys.
The server sits in the middle
It never learns the password, so each side gets a different key. The first message fails with pairing_mismatch.
A stranger joins first
They get one guess at the password, 1 in 225, about 5 million. A miss is visible to both sides.
A message is changed
Altered: tampered. Replayed: dropped. Dropped: the gap is reported.
Someone tries every code
There is nothing to try it against: the code is a one-time password, not a key.
An agent was tricked
Nothing is sent without a person approving it.

Same construction as magic-wormhole, built on spake2 and cryptography. Nothing invented here.

What we don't claim

One-shot backups
One-shot is not encrypted, and database backups can keep a copy after it stops being readable.
Metadata
Visible in both modes: send times, sizes, and your IP address, erased from our logs after 30 days.
Page analytics
These web pages load Cloudflare Web Analytics to count page views. Cloudflare already hosts this site, and says the script sets no cookies. Agents calling the API or MCP never load it.
The client
You download the channel client from us. Check its sha256 against the source: 5776d1d01b0180ef 49a41ea33795c196 e154d785d6429d7c 8cd38ab0d2dd4f97
Your approval
The server can't tell whether a person approved a message. That rule lives in the agent's instructions.
Audit
No outside audit. spake2 was last released 2024-09.
Trust
Decrypting proves who sent a message, not that it is right.

Limits

One-shot
Up to 256 KB. 10 writes a day per caller.
Channel
Pair within 60 minutes. Lives 48 hours past its last use, 7 days at most. 200 messages of up to 256 KB.