Progress
Last updated 2026-09-19 (evening)
This page is the ledger. It lists what already runs in the app, what is built and tested but not yet wired in, and what is still ahead — for security and for anonymity, the two things YGOOW exists for. A line moves to done only when it runs in the app. Library code, tests and designs are listed separately, however good they look.
done runs in the app
built implemented and tested in the protocol library, not yet in live conversations
next at the top of the queue
ahead planned, not started
Where things stand
Encryption
| Status | Where it stands | |
|---|---|---|
| End-to-end encryption (AES-256-GCM) | done | Native, on the phone’s AES instructions; timing measured on ARM64 against the leak the old library had. |
| No decryption oracle | done | A wrong key gives a locked block: no error, no hint. |
| Key stretching for weak secrets (Argon2id) | done | Memory-hard; the strength meter is shown as a ceiling, because we measured it overstating. |
| Forward secrecy in contact conversations | next | The key advances with every message and used keys are erased. The gap today: a conversation’s starting key comes from the two long-term identities, so someone who recorded your traffic and later copies and unlocks your profile can decrypt earlier messages, including ones you deleted. Locked-content modes, where the second secret is not stored, are not affected. |
| Post-compromise security (Double Ratchet) | built | Implemented and tested against vectors. Live conversations do not run it yet; wiring it in also closes the forward-secrecy gap above. |
| Post-quantum hybrid (ML-KEM-768 + X25519) | built | Implemented, with the timing leak (KyberSlash class) found on ARM64 and fixed. Not yet in live conversations, so “record now, decrypt later” is not yet covered. |
| Constant-time primitives on ARM64 | done | AES-GCM and Ed25519 run natively; Shamir arithmetic rewritten branch-free; X25519 measured clean. The self-test shows which implementation actually runs. |
Knowing who you talk to
| Status | Where it stands | |
|---|---|---|
| Local identity, no account, no phone number | done | Keys are generated and kept on the device. |
| Several identities behind one app-lock | done | Separate keys and contacts per identity; you choose which one each contact sees. Each identity’s conversations and invites use its own Tor circuit; a Dead Drop or a key fetched from a link gets a one-off circuit of its own. |
| Safety number over both keys | done | Since 2026-09-19 it covers the identity and the encryption key of both people. Before that, a swapped encryption key would have passed a “matching” number — found in our own review, fixed the next day. Verifications made with the old number expire. |
| Forged contact codes rejected | done | A code with a known identity but a different encryption key is refused with a warning, instead of silently replacing the contact. |
| Post-quantum key in the contact code | built | The format exists; it needs a split QR code, because one code would be too dense to scan. |
Metadata and anonymity
| Status | Where it stands | |
|---|---|---|
| Tor by default, relay as an onion service | done | The relay never sees your IP. Leaving Tor is a deliberate, confirmed step. |
| Tor enforced from the very first connection | done | The network policy now comes from your setting before the app draws its first screen, so “Tor still starting” is no longer mistaken for “Tor switched off”. Anything that would have gone out over the open internet while Tor starts is refused instead. |
| Size padding | done | Every frame padded to a size class with a 384-byte floor; measured at 0.043 bit of message length. |
| Rotating conversation addresses | done | A new, unguessable address about every 15 minutes. This limits what an outside observer gets from one address — not what the relay can link. |
| Catch-up without a trail | done | Fetching missed messages no longer carried a value that tied a conversation’s addresses together (100 % → 0 %). |
| Cover traffic (optional high-risk mode) | done | Decoy frames indistinguishable from real ones by size and spacing (measured). Off by default; costs ~6.3 MiB a day per open conversation. |
| Relay-side timing | next | Measured: from timing alone the relay can group one phone’s addresses — 85–90 % after one 15-minute period. The fix under decision is one fixed-rate channel per device with all conversations inside it. |
| Message counter in the header | next | Measured 2026-09-18: the per-conversation message number is visible to the relay and links a conversation across address changes (81–89 % among 20 conversations, 10 % among 2 500). Fix: encrypt the header. |
| Group rooms and the relay | ahead | Room key traffic now travels on the room’s own address and no longer touches your contacts’ addresses (0 frames). What the relay still sees: that a membership change happened (100 % in our model), and — through the message counter — how many members are sending (95–100 %). Closing that needs the encrypted header and the single-channel transport. |
Groups
| Status | Where it stands | |
|---|---|---|
| Per-sender keys | done | Each member has their own key chain, and used keys are erased. |
| Forward secrecy for key delivery | ahead | A member’s sender key is still delivered under long-term keys, so it has no forward secrecy of its own. |
| Signed membership changes | done | Every add and remove is a signed change; removing someone moves the room to a key they don’t get. |
| Messages survive a crash mid-send | done | A one-to-one message leaves the phone only after the step it used is saved, so a crash can’t make the next message reuse a number the other side would reject. |
| Changes reach members who were away | done | Delivered in the background now. In our model, members on the same key within 24 hours went from 3–9 % to 100 %, and lost room messages from 29–55 % to under 0.5 %. Someone away for more than 24 hours sees a banner and rejoins with a new invite code. Device test pending. |
| Groups that split heal themselves | done | Two conflicting changes made at once resolve the same way on every phone, without a coordinator. |
| Replay protection for key distribution | next | A replayed key message can make a phone show an old group message twice. It doesn’t expose new content, but it breaks integrity. |
| A removed member stops seeing room traffic | ahead | After removal they can’t read new messages, but can still tell when the room is active. |
Your phone
| Status | Where it stands | |
|---|---|---|
| App-lock: password, file, link, quorum, YubiKey | done | Any combination; a YubiKey over NFC as an optional second factor. |
| Decoy profile, measured over a lifetime | done | Without the decoy password, one or two copies of storage and the unlock time don’t reveal the hidden profile (measured on months of simulated use). With it, two edges remain and are written down. |
| Panic lock, no screenshots | done | Disarms biometrics; the screen is blocked from screenshots and the app switcher. |
| Backup file | done | 256 MiB Argon2id, padded, optionally without history; a stricter password gate than the rest of the app. A crafted file can no longer demand gigabytes of memory or minutes of work before the password is even checked. |
| Auto-lock | done | On by default at 5 minutes, adjustable in settings. The app locks and wipes its keys while it sits in the background. With background delivery switched on, the keys stay so messages can arrive — and the app still asks for your secret when you come back. |
| No Google in the loop | done | Notifications without Firebase or a push broker, and with no sender or content. On Android 15, which caps background work at 6 hours a day, the app stops cleanly at the cap, says so, and resumes when you open it. |
| Keyboard and clipboard | done | Text fields tell the keyboard not to learn what you type. Codes you copy are marked sensitive (no clipboard preview on Android 13+) and cleared after 45 seconds. |
| Encryption fallback | done | If the native encryption library fails to load, the release build refuses to start instead of running on the slower implementation whose timing leaks. |
The relay and the release
| Status | Where it stands | |
|---|---|---|
| No accounts, no user table, minimal logs | done | The relay keeps ciphertext for 24 hours; an hourly job deletes it. |
| Server backups follow the 24-hour rule | next | The backup job now keeps the structure of the message, session, invite and Dead Drop tables but none of their rows, and leaves the onion key out of the code archive. Live once the updated job runs on the server. |
| Resource limits on the onion service | done | Flooding a connection no longer grows the server’s memory, and a sustained flood closes the connection. Requests over Tor share one global budget instead of trusting headers the client sets. |
| Release builds that can’t ship with a development key | done | A release build without the real signing key now stops with an error instead of quietly using a development key. |
| Warrant canary, security contact | done | Canary re-signed quarterly; reports to security@ygoow.com (PGP on the security page). |
| Independent audit | ahead | Committed to, when it can be paid for. Nothing on this site calls the project audited. |
Recently
- 2026-09-19 — A batch of hardening outside the research track. Tor is enforced from the first connection. Auto-lock is on by default and locks in the background. Release builds refuse a development key. A crafted backup can’t stall the app. The keyboard doesn’t learn what you type. Each identity’s invites use its own circuit. Background delivery survives Android 15’s daily cap. The WebSocket parser no longer loses the first message after connecting and enforces limits. The relay’s limits can’t be bypassed over Tor.
- 2026-09-19 — Safety number covers both keys. Our own review found that the number compared only the identity key, so a swapped encryption key would have passed. Fixed the next day: the number covers both keys of both people, forged contact codes are refused, and old verifications expire.
- 2026-09-18 — Header counter measured. The message number in each frame’s header links a conversation across address changes. Measured and published here before the fix; header encryption is next.
- 2026-09-17 — Dead Drop. One-time notes by link or QR, in the app and in a browser at /d; the key stays in the link’s fragment and never reaches the server.
- 2026-09-17 — Groups converge in the background. Membership changes reach members who were away, instead of only those who opened the room within half an hour.
- 2026-09-17 — Nothing lost after an absence. Messages to someone offline for more than 15–30 minutes could be silently lost in the default setup (57–58 % in our model). Now 0 %, and the catch-up no longer links a conversation’s addresses.
- 2026-09-17 — Native AES-GCM on the phone. The timing leak in the old library is gone on the native path, and encryption is about 290× faster.
- 2026-09-17 — Hidden profile redesigned and re-measured. No data loss across 600 simulated lifetimes; without the decoy password, storage copies and unlock time give nothing away.
- 2026-09-10 — Stronger adversary, corrected claims. A likelihood-ratio relay groups a phone’s addresses 85–90 % after one period; the whitepaper now says so.
- 2026-09-10 — Location lock removed. It asked Google for the phone’s position outside Tor. Why we removed it.
- 2026-09-03 — Background poll redesigned. It was the relay’s best clue that several addresses belong to one phone (77× above chance).
- 2026-09-02 — Backup without history. The file’s size still gave away the rough size of your message history, so export can now leave history out.
- 2026-08-26 — Relay authorization gap closed. Found in our August review and fixed.
- 2026-08-26 — Native Ed25519. The pure-Dart signer leaked the key through timing; signing now runs in a constant-time native library.
The full reasoning, with numbers, is in the whitepaper and its changelog.
What funding would buy first
YGOOW is built without outside money. Everything above is work we could do ourselves. Three things would move fastest with funding:
- An independent review of the protocol and its implementation — the one check we can’t do ourselves.
- Measurements on real traffic. Our traffic numbers come from models of the public protocol. A small lab — a few low-end phones and a capture setup on the Tor path — would measure the real app instead.
- Time for the single-channel transport. It is the one change that closes all four timing leaks we measured at the relay.