Unlinkable Inference: Private Sessions in Obscurify
Chats in the Obscurify web chat and Android app are now paid for with ‘blind signed’ vouchers (not your account key). Each conversation is a unique “prepaid session” (only identified by a random secret), which is paid for with these blind-signed vouchers. This means that we can verify that a session has been paid for, but we can’t tell what account paid for it, and can’t link multiple conversations to the same account. This is on by default (once you sign in to an account) and costs nothing extra. The code is open source: github.com/Obscurify-ai/unlinkable-inference
The problem with an account key
Obscurify accounts were already anonymous: just a 16 digit number, no email address, phone number or name required. But every chat you had was associated with your account key. So we could tell that the chat in which you asked about your lease and the one in which you asked about your health were from the same account. If one of them said who you were, they all did!
Most AI services (even many that claim to be “private”!) work like this. Your account is what ties your conversations together.
How it works
- Vouchers are blank credits that you have pre-paid for with your app, and spend on AI services. Your app generates these, and then “blinds” them. Imagine you wrote each voucher, and then sealed it in an envelope, lined with carbon paper. We can sign the vouchers (through the envelope!) and debit your account for the appropriate amount, and then your app can take the “envelopes” off. You have signed vouchers, and we have no idea what they are.
- A session is a conversation. To start a conversation, your app sends us a small number of vouchers, and a randomly generated secret, and we open a “prepaid session”. Your app doesn’t send an account number or cookie when it makes this request. We can verify the signatures on the vouchers and open the session, but we don’t know whose vouchers they are.
- Chat. Every message that you send in a conversation is authenticated by the secret that your app generated when it opened the session. Your account key is never used. Every reply is billed to the session, for the exact number of tokens.
- Change. When you stop chatting for 5 minutes, the session is closed. The balance remaining on the session is returned to your device as new vouchers (which we sign without seeing). You can use these to open your next session.
This is called a “blind signature”. Specifically, we use RSA blind signatures (standardized as RFC 9474), which were first described by David Chaum in 1982.
What we can see
On the account side, we can see that account 4f1c... paid $1.00 worth of vouchers at 10:02. On the session side, we see that session 7a9e... made 41 requests (worth 50¢). There is no information in our database that links these two database entries together (or that can link any two session entries together, for that matter).
There are still some things we can see, though. We read your prompts, because we have to pass them on to the model, so if you put your name in a prompt, we’ll see your name. We see your IP address too, unless you’re on Tor or a VPN (Obscurify has a Tor onion address). And there’s timing: if you’re the only person chatting at 4 a.m., that narrows it down a lot. It gets better as more people use private sessions.
The full threat model can be found in the repo.
You can’t lose the money
You can’t lose your money. Every voucher and session secret is derived from your account number. So if you reset your phone or wipe your Tor Browser window – you’re still ok. Just sign back in with your number, re-derive your wallet and you’ll get back any money you had left in any open sessions.
Sessions can’t overspend. A worst-case cost is calculated for each reply before it starts, and set aside from the session balance. If a session doesn’t have sufficient balance, the app will top it up (from your wallet) and try the reply again. You only pay for the tokens you actually use (rounded up to the nearest 1/1000th of a cent).
Plans
Casual and Pro subscribers get anonymous passes each month. A pass only reveals what plan you have (nothing else), and lets a session use the models you have access to without revealing your account.
For developers and agents
By default the API will continue to use your API key. If you want to take advantage of private sessions with a program like Claude Code or Codex (anything that speaks the OpenAI or Anthropic API) you can run our open source proxy:
cargo install unlinkable-inference-cli
unlinkable-inference serve
Then point your tool at http://127.0.0.1:8899 and give it your regular API key. The proxy will use that only to fill its wallet, it will never send your key with a chat.
Step-by-step setup for Claude Code, Codex, pi and MCP clients: Private sessions for the API, agents and MCP.
Open source, for any service
The unlinkable-inference library is written in Rust, and is open source under the MIT and Apache 2 licenses. This library also contains the server-side code, which means that any AI service provider can run it on their own servers and database, without having to use a middleman service. The library is also available on npm as WebAssembly, so it can be used from web pages. The command line proxy is GPL licensed. The source code, wire protocol specification and threat model are all available at github.com/Obscurify-ai/unlinkable-inference.
The term “unlinkable inference” was borrowed from the Open Anonymity Project, whose anonymous chat app (OA) uses a similar approach.
FAQ
Do I need to turn it on? No. Unlinkable inference is on by default in the web chat and the Android app (when you sign in with your account number).
Does it cost more to use? No, it doesn’t. Each conversation pays for its tokens, and when it ends you get the change back.
Does Encrypted mode use private sessions? No, not yet. Encrypted chats (aka TEE mode) still run through your signed-in account.
What if a reply is very long? A single reply in a private session can be up to 32,000 tokens. (On the most expensive models, that’s a bit less, to ensure that a single reply can never cost more than ~$1.)