/wipe overwrites the message log and VACUUMs; identity and friends stay. /wipe-all deletes the data dir after confirm so the next open is a new person. Neither runs without a typed confirm screen.
66 lines
2.3 KiB
Markdown
66 lines
2.3 KiB
Markdown
# OnionWire
|
||
|
||
Lean Tor messenger: one Rust process (ratatui + Noise IK + sqlite + in-process Arti).
|
||
Two people scan a QR, then chat. No hosted server. Identity is a public key; the onion is only a locator.
|
||
|
||
## First run
|
||
|
||
```
|
||
cargo run --release
|
||
```
|
||
|
||
Data lives in `ONIONWIRE_HOME` if set, otherwise `~/.local/share/onionwire/` (`onionwire.db` + Arti state, mode 0700). First open creates an ed25519 identity key. That key **is** you.
|
||
|
||
Arti bootstraps Tor and publishes a v3 onion service. Onion services in Arti are still **experimental**. OnionWire fails closed if the HS cannot come up — it does not fall back to a `tor` binary or C-tor.
|
||
|
||
## Friends are keys
|
||
|
||
A friend is an ed25519 pubkey (`UNIQUE(pubkey)`). The `.onion` on that row is only where they are reachable right now. Re-scanning the same `k` updates the locator; it never creates a second person.
|
||
|
||
## F2 QR
|
||
|
||
`F2` shows a terminal QR and the payload:
|
||
|
||
`onionwire:v1:k=…:o=…:spk=…:sig=…`
|
||
|
||
`F3` pastes a payload. Unknown `k` asks for approval. Same `k` already in the roster updates `onion` only.
|
||
|
||
## F4 rotate onion
|
||
|
||
`F4` is a locator change, not a new identity. Confirm by typing `ROTATE` (Enter alone does nothing).
|
||
|
||
- Your identity fingerprint stays the same.
|
||
- A new onion is published; the old one is hard-cut (no dual-host grace).
|
||
- Online friends get a signed `loc` frame.
|
||
- Offline friends cannot find you until they rescan the new QR. There is no directory.
|
||
|
||
## Fail closed
|
||
|
||
If a peer’s onion is down, send fails. v1 has no outbox, no retry queue, no DHT, no name server.
|
||
|
||
## Wipe
|
||
|
||
Composer (bottom of the roster screen):
|
||
|
||
- `/wipe` — confirm by typing `WIPE`. Overwrites the message log and `VACUUM`s. Identity key and friends stay.
|
||
- `/wipe-all` — confirm by typing `WIPEALL`. Deletes the data dir. Next start is a **new person** (new identity key). Esc cancels. Nothing is wiped without confirm.
|
||
|
||
## Seized laptop
|
||
|
||
v1 stores **plaintext** on disk:
|
||
|
||
- message log (sqlite `messages.plaintext`)
|
||
- your identity secret key (`self.identity_sk`)
|
||
- friend public keys and current locators
|
||
|
||
Full-disk encryption plus `/wipe` / `/wipe-all` is the mitigation. There is no sqlcipher in v1.
|
||
|
||
## Not in v1
|
||
|
||
Prosody, XMPP, s2s, MAM, carbons, outbox, multi-device, DHT / name server, sqlcipher.
|
||
|
||
Plan of record: `/home/lancelot/.hermes/plans/2026-09-10_004409-onionwire-lean.md`
|
||
|
||
## License
|
||
|
||
MIT
|