p
pastehere
How it worksFAQ
Engineering · 2026-06-10

How pastehere syncs your clipboard without ever seeing it

pastehere moves text and files between your devices through a server that can never read them. Here's the design: a PAKE handshake over a six-digit code, AES-256 end-to-end encryption, and public-key wrapping to add devices — and exactly what the server does and doesn't store.


The goal, and the constraint

The promise is simple: copy on one device, paste on another, with a server in the middle so the devices don't have to find each other on a network. The constraint is the interesting part — that server should be able to relay your data without ever being able to read it. Not "we promise not to look," but "looking is not possible, because what we store is ciphertext and we never hold the key."

That rules out the easy design (encrypt in transit with TLS, decrypt on the server, re-encrypt to the other device). Everything has to be encrypted on the device, under a key the server never learns. Which raises the hard question: how do two devices that have never met agree on a strong key, when all the user is willing to type is six digits — over a channel run by the very server we don't trust?

Device Aplaintext
seal →
Serverciphertext only
→ open
Device Bplaintext
The room key lives only on the devices. The server stores ciphertext, IVs, sizes and timestamps.

Six digits is not a key

A six-digit code has about 20 bits of entropy — trivially brute-forced if it were used directly as a key. The trick is to never use it as a key. Instead, pastehere runs a balanced PAKE (Password-Authenticated Key Exchange): a protocol where two parties holding the same short secret derive a strong shared key, such that a network attacker — even an active one who relays and tampers with messages — learns nothing that lets them guess the short secret offline. A wrong code, or a man-in-the-middle, simply makes the handshake fail.

Specifically it's CPace over the ristretto255 group with SHA-512, following the CFRG draft, with byte encodings checked against the official test vectors. Both devices derive a group generator from the code plus a random session id, each picks a secret scalar, and they exchange public points. From the shared point and a transcript of the exchange, each side hashes out the same 64-byte intermediate session key (ISK). The code shapes the generator, so only two devices that started from the same six digits land on the same key.

Device Acode + sid → g, scalar a
Yₐ ⇄ Y_b
Device Bcode + sid → g, scalar b
CPace: each side computes the shared point and hashes the transcript to the same ISK. The server relays Y but can't derive the key.

From handshake to a confirmed key

The ISK is run through HKDF-SHA256 to split it into two keys: a MAC key and an encryption key. Before trusting anything, the devices do mutual key confirmation — each sends an HMAC tag proving it derived the same ISK, and the other verifies it with a constant-time comparison. If someone fed a wrong code or tried to sit in the middle, the tags don't match and pairing aborts. This is what closes the man-in-the-middle gap that a naive unauthenticated key exchange would leave open.

The room key, and sealing it across

A room's actual content is protected by a 32-byte (AES-256) room key, generated randomly on the device that creates the room. To get it to the second device, the creator seals it: AES-GCM encryption under the PAKE encryption key, with the session id bound in as additional authenticated data, then sends the sealed blob through the server. The other device, holding the same PAKE key from the handshake, opens it. The server forwards an opaque box; it never sees the room key.

At rest on each device, the room key is wrapped again — encrypted under a device-specific key-encryption key and stored in IndexedDB — and imported as a non-extractable key for actual use, so page JavaScript can encrypt and decrypt with it but can't read the raw bytes back out.

Encrypting what you paste

With the room key in place, every item you add — a line of text, a link, an image, a file — is encrypted with AES-256-GCM, a fresh random IV per item, and the room id bound as additional authenticated data so a ciphertext can't be replayed into a different room. Files are chunked and encrypted the same way. What reaches the server is the ciphertext, the IV, and metadata it genuinely needs to do its job: the byte size and a timestamp. Not the filename in the clear, not the text, not the key.

Adding a third (or fourth) device

Re-running the PAKE every time is fine for pairing, but once a room exists, new devices are added with public-key cryptography. Each device has an X25519 key pair. To grant a new device access, an existing one wraps the room key to the newcomer's public key using ephemeral-static ECDH (an HPKE-style construction): a fresh ephemeral key pair, an X25519 shared secret, HKDF-SHA256 — with both public keys mixed into the salt so a swapped key is detectable — and AES-256-GCM to encrypt the room key. Only the holder of the matching private key can unwrap it.

What the server can and can't see

Putting it together, here's the honest threat model. The server can see: that a room exists, how many ciphertext items it holds, their sizes and timestamps, and the coarse traffic pattern of devices syncing. The server cannot see: your text, your files, your filenames, the room key, or the six-digit code — and because the PAKE resists active attackers, a malicious server can't even quietly man-in-the-middle the pairing to learn future content without breaking the handshake and being noticed.

The limits worth stating plainly: this protects data in transit and at rest on the server, not a device that's already compromised — if malware is watching your screen or your clipboard, no transport design saves you. And metadata (sizes, timings) is real metadata. We minimise it, but we don't pretend it's zero.

Destroying a room

Because there's no account tying a room to an identity, deleting one is clean: destroying a room removes its ciphertext from the server, and clearing it from a device removes the wrapped room key there. There's no expiry timer doing this on a schedule — rooms persist so an offline device can catch up on reconnect — but the off switch is always yours, and once the key is gone, the ciphertext is just noise.

Why this shape

Every choice here serves the one constraint: the server relays but never reads. PAKE lets a human-friendly six-digit code bootstrap a real key without exposing it to brute force. AES-256-GCM with bound metadata makes each item tamper-evident and room-scoped. X25519 wrapping lets a room grow to more devices without weakening the model. The result is a shared clipboard that's genuinely end-to-end encrypted — not as a feature you switch on, but as the only way it works.