50 lines
2.1 KiB
Markdown
50 lines
2.1 KiB
Markdown
|
|
# wisp
|
||
|
|
|
||
|
|
Short-lived, end-to-end encrypted file sharing. Send a file to someone who
|
||
|
|
isn't online right now — they get a link, they get the file once, and then
|
||
|
|
it's gone. The server never has the ability to read what it's holding.
|
||
|
|
|
||
|
|
## Why
|
||
|
|
|
||
|
|
`flit` already does encrypted file transfer between devices, but it's
|
||
|
|
synchronous — both sides have to be online at the same time for the WebRTC
|
||
|
|
handshake. That's fine for "send this to my other laptop right now," and
|
||
|
|
wrong for "here's a file for you, grab it whenever."
|
||
|
|
|
||
|
|
wisp is the asynchronous counterpart: upload once, the recipient retrieves
|
||
|
|
later, on their own schedule. That async gap is the one thing flit's
|
||
|
|
architecture (zero server storage, direct P2P) structurally can't do — it
|
||
|
|
requires the server to actually hold ciphertext for a while, which is new
|
||
|
|
territory for this project family, not a variant of something already built.
|
||
|
|
|
||
|
|
## What it isn't
|
||
|
|
|
||
|
|
- **Not zipline.** Zipline is persistent link/screenshot hosting — you keep
|
||
|
|
the URL, the file stays. wisp is the opposite: single retrieval, then the
|
||
|
|
file is unrecoverable, by design.
|
||
|
|
- **Not flit.** Flit needs both peers online simultaneously and never stores
|
||
|
|
anything server-side. wisp is deliberately async and requires temporary
|
||
|
|
server-side ciphertext storage.
|
||
|
|
|
||
|
|
## Core model
|
||
|
|
|
||
|
|
1. Sender encrypts the file client-side (symmetric, libsodium secretbox —
|
||
|
|
same primitive flit's browser client already uses).
|
||
|
|
2. Ciphertext uploads to the server. The encryption key never leaves the
|
||
|
|
sender's browser except inside the URL fragment (`#key=...`), which
|
||
|
|
browsers never transmit in HTTP requests. The server only ever sees
|
||
|
|
opaque bytes.
|
||
|
|
3. Sender shares the link through any channel they like.
|
||
|
|
4. Recipient opens the link, downloads the ciphertext, decrypts client-side.
|
||
|
|
5. On successful decrypt, the client sends a short confirmation to the
|
||
|
|
server. Only then does the server delete the blob.
|
||
|
|
6. A TTL (default: a few days) is the backstop for links nobody ever opens,
|
||
|
|
so nothing sits on disk forever.
|
||
|
|
|
||
|
|
Full design, including why "delete on first byte served" is the wrong
|
||
|
|
default, is in [IMPLEMENTATION.md](./IMPLEMENTATION.md).
|
||
|
|
|
||
|
|
## Status
|
||
|
|
|
||
|
|
Design only. No code yet.
|