• 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.)

Proposed Solutions:

  1. 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.
  2. 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.
  3. 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.
  4. 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.

  • What is the monetary value of the "resource" being accessed? – Robert Harvey Jun 12 '19 at 19:08
  • 1
    I think the best solution will depend a lot on the business context of these receipts. If this is consumer-oriented and can't e.g. rely on an app, then managing private keys is going to be difficult. In contrast, requiring users to be signed in to their account is an easy solution that largely prevents reuse. – amon Jun 12 '19 at 19:15
  • @RobertHarvey, that's really hard to say. A solid example would be a news-article or blog post. As a first-approximation, I think we can say that access to the resource is worth the cost of the Receipt, which is likely to be 0.01 - 0.10 USD. – ShapeOfMatter Jun 12 '19 at 19:49
  • 2
    I think I'm missing something. How does a user share their receipts amongst their clients, if neither the service, nor the notary are aware of either users or their clients? It feels like you are stating that you do not wish to know about this information (which is okay), but then wish to place a constraint on the system that requires that information. Either the information is available to you in some form and you can act on it, or the information is not available and this constraint is a pipe dream. Consider introducing an account keeper who can associate receipt thumbnails to users. – Kain0_0 Jun 13 '19 at 1:17
  • 1
    Yes, blind signatures are an interesting use of cryptography. Its mathematically sound, you are essentially signing a class of messages which is difficult to perform a birthday attack on. If you are relying on the base difficulty of sharing data, then do nothing. If you however wish to enforce a constraint, it must be against some form of information. You could phrase it as reciept = user, in which case you would need a way to identify the user, or the class of user that is hard to find a birthday for. Or phrase it in terms of access: no more than X uses per day, no more than y requesters. – Kain0_0 Jun 14 '19 at 2:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.