Pixieby Sociofabric

Sender Unlinkability: The Pseudonym Problem

Hiding your name is not the same as hiding that it's you. A relay that never learns "Alice" can still learn "the same unnamed person who messaged Bob at 9, Carol at 10, and a support line at 2am," and that shape is often enough to put a name back on.

Sealed sender removed the sender's identity from the envelope and left one thing behind: a 16-byte cert_id, an opaque ticket number the relay needs for revocation (cancelling a bad certificate mid-life) and for abuse control. This article is about the surprisingly sharp leak that one small field creates, and the shipped fix.


1. Linkability, and why a pseudonym is dangerous

Cryptographers distinguish anonymity (the system doesn't know who you are) from unlinkability (the system can't tell that two of your actions were done by the same someone). They are different, and the second is easy to lose while thinking you have the first.

The cert_id is stable for the life of a certificate, roughly a day.

So even though the relay never learns "Alice," it can group every message carrying ticket #7 into one bucket and study that bucket: how many conversations it touches, at what hours, in what bursts, in reply to what.

That bucket is a pseudonym, and pseudonyms de-anonymize through pattern. This is the entire field of traffic analysis: working out who is who from the patterns of communication alone, without reading a single word of content.

WHAT ALICE SENDS WHAT THE RELAY KEEPS ALICE NAME NEVER ON THE WIRE TO BOB · 9 TO CAROL · 10 TO SUPPORT · 2AM SAME TICKET #7 ON EVERY ENVELOPE RELAY ONE BUCKET · TICKET #7 9 · CHAT 1 10 · CHAT 2 2AM · CHAT 3 HOURS · BURSTS · WHO-WITH-WHOM ONE OUTSIDE LABEL → 'ALICE' NO NAME, ONE TICKET — EVERY CHAT LANDS IN THE SAME BUCKET

So a stable per-user ticket, even an anonymous one, is a real leak. We want the relay to lose the thread between a person's conversations.


2. Why we can't just delete the ticket

The tempting answer is to drop cert_id from the envelope entirely. We cannot (not without moving the jobs it does somewhere else first) because the relay uses it for two things that genuinely have to happen at the moment a message arrives:

Both are legitimate, both need some stable handle, and neither is allowed to be the user's identity. The tension is real: the same field that enables anonymous revocation is the field that enables pseudonymous clustering.


3. The shipped fix: a different ticket per conversation

The resolution is to keep a stable ticket, but make it stable only within a single conversation rather than across a user's whole life. Instead of one certificate per user per day, Alice mints one certificate per conversation: a distinct cert_id for her chat with Bob, another for her chat with Carol.

The trick that makes this cheap and private is where the certificates are filed.

Alice caches one certificate per conversation, indexed under that conversation's local channel key: a secret she and her partner already share, and which is never transmitted to anyone.

The mint request itself is byte-identical every time, so credential-svc (the separate identity service that issues these certificates) cannot tell which conversation it just issued for. The separation happens entirely on Alice's device.

Now walk it from the relay's side.

It still sees a stable ticket inside a single conversation. But it already knew those messages belonged together, because a conversation shares a routing subject anyway: the single address every message in that chat is published to.

What it has lost is the ability to tie the Bob-ticket and the Carol-ticket to each other. Alice's separate conversations are now separate unlabelled buckets.

ALICE ONE LOCAL CHANNEL KEY → ONE TICKET RELAY BUCKETS CHAT · BOB B7 CHAT · CAROL C2 CHAT · HELP S9 BUCKET B7 BUCKET C2 BUCKET S9 BOB CAROL HELP NO CROSS-CHAT JOIN STABLE INSIDE ONE CHAT · UNLINKABLE ACROSS ALICE'S CHATS

The analogy is using a different alias at every venue. A doorman at one club can still recognize "the guy in seat 4 all night," but no one can cross-reference the clubs to discover it's the same person making the rounds, because the name on each wristband is different and unlinkable.


4. What it costs

Not much, which is why this is the shipped choice rather than a someday-plan:

That is the entire price for erasing cross-conversation linkage at the relay.


5. The honest residuals

We name what this does not fix:

None of these reconstruct a cross-conversation social graph, which is the leak we set out to close. But honesty is the house style, so they are on the record.


6. The endgame we didn't ship (yet)

There is a cleaner design, and it is worth stating because it is the recommended next step. True Signal-style sealed sender removes cert_id from the envelope entirely. In that world the relay does no per-message identity check at all. Revocation moves entirely to credential-svc: a banned account simply cannot mint fresh admission tokens, so its messages stop being admitted rather than being recognized-and-rejected. And all relay-side abuse control rides on the single-use admission token, which is already anonymous and unlinkable by construction.

CURRENT · SHIPPED ENDGAME · TOKEN ONLY OUTER ENVELOPE CERT_ID · STABLE TOKEN · ONCE RELAY CHECKS BOTH ONE CHAT-SCOPED HANDLE REMAINS CREDENTIAL-SVC BUDGET + REVOCATION RELAY VALID + UNSPENT BANNED USER NO FRESH TOKENS NO IDENTITY CHECK AT THE RELAY NO STABLE CERT_ID ON THE WIRE CUT OFF THE MINT · ADMIT ONE-USE TOKENS · DROP THE TICKET

We did not ship that yet because it changes both the envelope format and the admission path: the riskier surgery. Per-conversation certificates deliver the property that actually matters, no cross-conversation linkage, as a localized, low-risk change that touches neither. It is the classic engineering call: ship the 90% that removes the real leak now, keep the elegant 100% as a planned migration. When the envelope format next changes, dropping the ticket is the plan.


References & further reading

← Sealed Sender: Hiding Who Is TalkingThe Envelope: Minimizing What the Relay Must See →