- A Client is requesting a resource from a Host multiple times, usually with minutes or hours between requests.
- The Client has a signed, verifiable token, which we'll call a Receipt, that asserts that they should be allowed to access the resource. (The Receipt will eventually expire, say at the end of the month.)
- The Host has no way of knowing (and should have no way of knowing) who the Client is beyond the fact that a given receipt is being reused.
- EDIT: The Receipts come from a third party, the Notary. The Notary does have a meaningful idea of who a user is (in the sense that they can charge them money), but does not know which user owns which receipts. (Receipts are validated using a blind signature scheme.)
Receipts cost money. (We're building a micro-transaction service; so they cost ~0.10USD) We don't want users (Clients) posting their Receipts online for public use, or otherwise sharing Receipts.
(EDIT: The goal isn't to prevent anyone from ever sharing a Receipt; individual Receipts just aren't worth that much. The goal is to prevent (or make sure we can combat) anyone making a system for sharing Receipts on a large scale.)
Note that in this model a "user" may have multiple "Clients" running on different machines, and will share Receipts among their Clients.
(EDIT: How they do this isn't set-in-stone yet; suppose there's a SaaS party offering encrypted private cloud storage, similar to a password manager.)
- Have the Client create a public/private key pair for each receipt (or however often the Client wants to). The public key will be submitted with the Receipt, and whenever the Host sees a given Receipt for the first time they'll store the accompanying public key so they can verify that future submissions came from the same person (even though they don't know who that is).
- cons: This just moves the "secret that shouldn't be shared" from the Receipt to the private key.
- pros: A private key really is easier to keep secret, in particular because, while the Receipt is sent to the Host, the private key never leaves the Client's control.
- Have the Host give the Client a single-use Token (as part of their normal response) to be included with their next submission of a given Receipt. These Tokens can be quite small. Re-submission of a Receipt (even once) without the expected Token is evidence that the receipt has been shared.
- cons: This will make both systems (Client and Host) harder to implement. It's convoluted and error-prone. Because Clients owned by a single user will share Receipts, some "false positives" are inevitable. Furthermore, sharing Receipts inappropriately is still possible using a system not too different from how well-behaving users will share Receipts among their devices. In this sense this solution relies on incompetent members of they hypothetical sharing pool accidentally violating the Token chain.
- pros: Building a sharing pool would be relatively difficult, and as a pool scaled up in members and usage it would become increasingly non-performant (because of locking) or increasingly likely to break Receipts (because they'd been noticed as shared). Additionally, a "good samaritan" in the sharing pool would be able to break the shared Receipts by intentionally violating the Token chains.
- Give "good samaritans" a specific function for invalidating receipts.
- cons: Does nothing to directly prevent sharing, it relies entirely on the idea that any hypothetical sharing pool would either not scale, or eventually be infiltrated by some kind of defector.
- pros: It's much easier to implement. Additionally, if combined with #1, then the Host would have a signed invalidation request they could present if their decision to reject subsequent submissions of that Receipt were ever challenged.
- EDIT: Rate-limit per-Receipt submissions. For example specify that receipts can't be used more than five times in an hour, or 10 times in the Receipt's lifetime. Thank-you @Kain0_0 for the suggestion.
- cons: Does nothing to directly prevent sharing. May limit usage of otherwise compliant users (for better or worse).
- pros: Places a hard limit on how much a given receipt could be shared in practice.
Originally I was planing on doing #1 and #2,
but having thought about it for a couple days I'm thinking #1 and #3 (or maybe just #3) would be easier and good enough.
Do people have suggestions for any (combination) of the above solutions, or other solutions I haven't listed?
Are there important angles I've overlooked?
EDIT: Additional context: This is the protocol I'm working on, in case people want to learn more or get more deeply involved.