Unlinkability & Threat Model¶
This page formalizes the threat model under which the payment scheme achieves unlinkability, describes the adversary's capabilities, and argues why Mint and Pay operations cannot be linked.
Definitions¶
Token. A token T = (payload, σ) where payload encodes a TokenPayload containing a fresh one-time public key, and σ is a BLS signature under the system public key PK.
Link. A link is a mapping from a Pay transaction to the Mint operation that originally created the spent token. Formally, given the transcript of a Pay operation (the SignedTransaction seen by the servers) and the set of all Mint transcripts, the adversary wins if it can identify which Mint produced the token being spent with probability significantly better than 1/N, where N is the number of minted tokens.
Adversary Model¶
We consider a passive adversary that can observe all server-side state and all network messages, but does not deviate from the protocol.
What the adversary observes¶
| Observable | Content |
|---|---|
| Mint requests (all servers) | SignedMintRequest = { payload: MintRequest, signature } where MintRequest contains { id, blinded_message: H' } |
| Pay requests (all servers) | SignedTransaction = { payload: Transaction, signature } where Transaction contains { token: Token, recipient_blinded_payload: H'_r } |
| Server state | Client registry (id, balance, public-key nullifiers), token nullifier set |
| Network metadata | Timing and source IP of requests (not exploited in our model) |
What the adversary does not observe¶
| Secret | Held by |
|---|---|
Blinding factor r used during Mint |
Minting client |
One-time secret key sk of the token |
Token holder |
Blinding factor r_r used during Pay key generation |
Recipient client |
Plaintext TokenPayload before it is embedded in the final token |
Client (sender or recipient) |
| Mapping between blinded and unblinded messages | Client |
The adversary may know:
- The total number of minted tokens and the number of payments.
- Client identities associated with Mint operations (since
MintRequest.idis in the clear). - The system public key
PKand all server key sharessᵢ. - The full protocol specification.
Why Unlinkability Holds¶
The core argument¶
During Mint, the server sees a blinded message:
During Pay, the server sees the spent token:
For the adversary to link Pay to Mint, it must determine which H' corresponds to which TokenPayload. This requires inverting the blinding:
Since r is a uniformly random scalar in Z_q known only to the client, and H' is a uniformly random element of G₂ from the server's perspective, the distribution of H' is independent of the underlying TokenPayload given the adversary's view.
Unlinkability Through the Protocol¶
The following diagram traces which values are visible at each stage and shows that no common identifier persists across Mint and Pay from the servers' perspective.
flowchart LR
subgraph Mint["Mint (server view)"]
M1["client_id"]
M2["H' = r·H(TP)"]
M3["σ'ᵢ = H'^{sᵢ}"]
end
subgraph "Client (private)"
B1["r (blinding factor)"]
B2["TokenPayload (TP)"]
B3["sk (one-time key)"]
B4["σ = r⁻¹·σ' (unblinded sig)"]
end
subgraph Pay["Pay (server view)"]
P1["Token = (TP, σ)"]
P2["H'_r = r_r·H(TP_r)"]
P3["σ'_r,i = H'_r^{sᵢ}"]
end
M2 -. "r is secret<br/>cannot invert" .-> P1
B1 --> B4
B2 --> B4
style M2 fill:#fbb,stroke:#900
style P1 fill:#bfb,stroke:#090
style B1 fill:#bbf,stroke:#009
Red = blinded (server sees). Green = unblinded (appears in Pay). Blue = secret (never leaves client).
The server sees H' during Mint and (TP, σ) during Pay, but has no way to connect them without r.
Additional Unlinkability Guarantees¶
Fresh keys per token¶
Every Mint and every Pay recipient generates a fresh one-time key pair. No key is ever reused, so public keys embedded in tokens cannot be correlated across operations.
Blinded message nullifiers¶
Servers track blinded messages in per-client nullifier sets (public_key_nullifiers) to prevent a client from minting two tokens with the same blinded payload. These nullifiers are blinded values, so they reveal nothing about the underlying token.
No linkage via signatures¶
The final token signature σ is a standard BLS signature that any holder of SK could have produced. It carries no information about which specific set of servers contributed partial signatures or what blinded form was used.
Recipient blinding during Pay¶
During Pay, the recipient also blinds their new token's payload before it is sent to the servers. This means the servers cannot link the new token issued during Pay to the recipient either, providing forward unlinkability in payment chains.
Summary of Security Properties¶
| Property | Mechanism |
|---|---|
| Unforgeability | BLS signatures under PK; only a quorum of servers can produce valid partials |
| Authorization Unforgeability | Mint/Pay requests are signed by the client's key; servers verify |
| No Double Spend | Token nullifier set — each token can be spent exactly once |
| Liveness | Broadcast to all, require only f+1 responses; tolerates f omissions |
| Conservation of Value | Mint deducts balance; Pay atomically spends 1 and creates 1 |
| Unlinkability | Blind signatures hide token content from servers; fresh keys prevent cross-operation correlation |