Sept. 10, 2026

Measured, not assumed

Every security page on the internet says its cryptography is “constant-time” and its metadata is “hidden”. Almost none of them say how they know. For the last six weeks we have been finding out how we know — by measuring the shipped code on the class of phone it ships to, with the pass/fail criteria written down before each run, and by publishing the results whether or not they flattered us.

This post is the digest. The full protocols, with the predictions that missed, are the source for the whitepaper’s new §7, §9 and §11.

The method, because it is the point

Each measurement is a card: a question, a named adversary, acceptance criteria and predictions committed before the run, a null control and a positive control in every comparison, three replications, and a ledger of which predictions held. The ledger is not decorative. One card records four misses against one hit; another records that all three of our predictions about an adversary’s strength were wrong in the same direction, by 6–24×. A method that cannot embarrass you cannot correct you either.

Two rules did most of the work. Measure on the target. Our ML-KEM reference had a secret-dependent division that was invisible on a desktop — the compiler strength-reduces a constant divisor — and produced a 15.6 % timing delta on the ARM64 phone. An audit that stopped at the desktop would have signed it off. A negative result needs a positive control. Our first timing run of the Ed25519 signer, in a debug build, saw nothing. The positive control — a leak we already knew was there — also saw nothing, so the run was thrown out, and the release build found the leak at |t| = 71.

What we found and fixed

What we found and have not fixed

Three claims we withdrew

This is the part most projects would edit quietly.

“The relay cannot batch addresses into one device.” The whitepaper said that because conversation addresses rotate every 15 minutes with a per-conversation phase, the relay could not tell which addresses belong to one phone. After redesigning the poll, a phase-histogram adversary confirmed it: grouping at 1.9–3.1× chance. Then we built the adversary we should have built first — a relay computing likelihood ratios over the public schedule — and it groups a device’s addresses 85–90 % after one epoch, 99.8 % within 30 minutes, with a thousand devices in the population making no difference. The resume-after-background timings do the same at 96–98 % after three resumes. The earlier number was a property of the weak measure, not of the schedule. The claim is gone from §6; §7 now says what the relay learns — a persistent pseudonym per device, from timing alone — and that two designs to close it are measured and under decision. The related claim that separate personas “don’t reveal that they share a device” fell with it: the poll round covered every identity at once.

“The relay cannot tell when you actually send.” Cover traffic does what it does inside an open conversation — 0.0018 bit between a real frame and a decoy. It does not hide that a conversation is open, it is off by default, and in the default configuration the relay keeps 98.5 % of the information about when you talk. The sentence now reads: with cover on, the relay cannot tell which frames are yours.

“The strength you see is the strength you have.” We measured the entropy meter against password classes of known construction. For a “word + digits + symbol” password it overstates by a median of 45 bits and waves 97 % of that class through the backup export gate without comment — while rejecting 37 % of genuinely random 8-character secrets. The meter is now labelled as a ceiling — at most this strong — and the export dialog says so. What protects a sealed file is the cost of one guess, not the number on the meter.

A fourth correction is smaller but of the same kind: our documents said the backup file’s padding “hides the scale of the profile”. It hides the number of contacts, rooms and unlock conditions; it does not hide the order of magnitude of your history (1.5 of 2 bits leak, and no padding within budget fixes it). So the export now offers a file without history.

What this is not

It is not an audit, and we do not call it one. An audit is someone else, with no stake in the answer, checking the work. What we have done is the work they would check, done in the open and before we ask anyone to check it — with the unfixed findings listed next to the fixed ones, because a list with only the fixed ones is marketing.

The whitepaper carries every number above and a changelog of what it used to say. If you can build a stronger adversary than ours, we want to hear about it.

Your key, your rules — everything else is redacted.


← Back to blog