[hashcash] Opportunistic signatures - a proposed design

  • From: Jonathan Morton <chromi@xxxxxxxxxxxxxxxxxxxxx>
  • To: hashcash@xxxxxxxxxxxxx
  • Date: Sun, 29 Aug 2004 16:31:32 +0100

It's recently become clear that to reliably prevent spammers from producing enough hashcash to continue delivery at an economic rate (for them), we will have to set the hashcash bar so high that it will be impractical for several classes of user to compute hashcash for every message they send.

Opportunistic signatures provide an authentication method strong enough to build a whitelist on, alleviating the need for users to compute hashcash for messages as part of an established bidirectional correspondence. An ideal implementation would make signature forgery difficult, yet be lightweight, essentially transparent to end-users and require no additional configuration.

Examples of bidirectional correspondence, to which opportunistic signatures can be applied, are: friends or relatives, opt-in mailing lists, corporate workgroups, inter-corporate mail, some sales and customer service.

This proposed design builds a signature from a (possibly low value) hashcash token, to provide protection against replay attacks, and a random key which is unique to a particular pair of correspondents. The signature itself is presented in a message header separate from the hashcash token. The following is a concise description of the signature format and operation, summarised and corrected from earlier posts.

The signature is made by concatenating the SHA1 representation of the hashcash token for the message with the key, and then computing the SHA1 hash of that. An encoded representation of this hash is then placed in a message header. (Precise format details for this header, and for the hashcash extension field are not yet finalised.) The signature is associated with a single sender, who is identified using a hashcash extension.

The recipient verifies the signature by first verifying the hashcash token it is built upon. The token must be valid and unique (that is, not double-spent), but may have a particularly low value - perhaps 8 or 10 bits. The recipient then recomputes the signature by the same method as the sender (using the key associated with the sender identified by the hashcash token), and compares it with that received in the message. If multiple hashcash tokens and/or signatures are present, some searching may be needed to find a valid combination.

If no signature can be verified, message handling should proceed as if there were no signature, even if an invalid one is present.

The key is generated at the sender end, and transmitted to the receiver during a "handshake period" at the beginning of the correspondence, using the hashcash extension field and an elevated bit count. It is encoded but not encrypted for this transaction. The rationale is that most of the time, the key will not need to be transmitted more than once, and interception of this single message is both unlikely and relatively low-impact. (If your mail is getting intercepted, you have bigger problems than just spam.) Different keys are used for each direction of the conversation, and for each sender-recipient pair.

More than one key may be associated with each user in each conversation, though implementations should place a sensible limit on this number. This allows users with multiple e-mail accounts with the same address, or computers in more than one location without a shared filesystem, to use opportunistic signatures without additional usability burden. The sender attaches only one signature to each mail (per recipient) - the one generated by that machine or for that account. The recipient should check signatures against all known keys for that sender, returning a valid result if any one matches.

The "handshake" at the beginning of the correspondence begins with an unsigned message being sent from one party - Alice - to a second - Bob. The hashcash value required for this message is that of an unsigned message - suggested 25 bits. Bob sees that the message has a valid hashcash token attached, so knows that Alice supports hashcash.

If Bob decides he wants to talk to Alice, his first message will contain a new key to be used for that conversation, and will be signed with that key. (Alice's first message was not signed because she did not know Bob supported hashcash.) The hashcash value required for this message is that for introducing a key - suggested 28 bits. Alice receives this message, verifies the hashcash, makes a note of the key, and verifies the signature.

Her next message will contain her own new key, will be signed, and will also contain acknowledgement of receipt of Bob's key. The hashcash value required for this message is that for introducing a key. Upon receipt, both users now have an established correspondence, with keys.

Bob's second message will contain acknowledgement of receipt of Alice's key, and will be signed, but will not contain a key because Alice already knows it and has acknowledged this fact. The hashcash value required for this message is that of a signed message - suggested 10 bits. All future messages between Alice and Bob contain confirmation that valid keys are known.

Senders should rotate keys periodically. This is done by including a random perturbation value in a signed hashcash header. The rotation is only valid if the associated signature also is, and an additional signature is present using the new key. The new key is equal to the SHA-1 hash of the old key concatenated with the perturbation value - this makes it practically impossible to force the key to a particular value. The recipient should acknowledge receipt of the rotation on the next message, and immediately stop accepting signatures on the old key. The sender should sign using both old and new keys until the acknowledgement is received.

Recipients should occasionally clear out stale keys from their database. A key that has not successfully verified any signature for an extended period of time (measured in months) can be safely thrown away. If new correspondence begins between these users, fresh keys are generated.

Similarly, senders should clear out stale keys. A key which hasn't been used to sign a message, and where no confirmation that the other correspondent knows the key has been seen, both for an extended period, can be thrown away and no longer used for signing.

The above protocol works even if Alice or Bob is a mailing list server. A bidirectional correspondence can be set up via the double-opt-in process which any reputable mailing list should employ, even if the list is intended for announcements rather than discussion, as long as the listserv understands hashcash and signatures. The listserv may also choose to use the signatures as an authentication mechanism for posting, but any issues surrounding this should be carefully considered by implementers.

Note that a correspondence is not set up between one subscriber and another, unless they communicate outside the list - it is always between the subscriber and the listserv. The listserv, if it understands the necessary concepts, should strip out the hashcash token and signature from each message, and replace them with a valid signature of it's own. Most good listservs send a separate message for each subscriber, so they will not receive a message with multiple signatures attached.

Keys can be manually revoked by the recipient, in case they are compromised. This can be as simple as a "remove from whitelist" button in the MUA. Listservs should also provide this feature, so that spammers abusing the list (and possibly using stolen keys) can be properly dealt with.

Comments and suggestions on the above are welcome.

--------------------------------------------------------------
from:     Jonathan "Chromatix" Morton
mail:     chromi@xxxxxxxxxxxxxxxxxxxxx
website:  http://www.chromatix.uklinux.net/
tagline:  The key to knowledge is not to rely on people to teach you it.


Other related posts: