hashcash是一个很有意思的技术,最早用于反垃圾邮件中。它的目的是,要求用户构造一个满足特定要求的字符串, 对其检验,若满足构造要求即证明用户已经花费了足够的时间认真地申请了这个资源(而非spamming)。

具体来说,要求是这样的:你需要在字符串里面申明一些信息,包括欲申请资源的标志,位数(含义见后文),时间,salt(含义见后文)等。要求:

  1. 这个字符串经过sha1进行散列后,其二进制表示中前N位是不少于字符串中申明的位数的连续“0”。
  2. 申明的位数不少于容许值。
  3. 字符串中标明的资源,必须和用户申请的资源标志一致。
  4. 字符串中的日期和当前日期的差值小于容许值。
  5. 这个字符串从前没有用过。

如果满足以上要求,资源提供者就可以考虑提供资源。否则,拒绝申请。

举例如下:

1:20:111007:foo::R1ecP62xhTg3vOu9:000000000000005xC1

上面是一个20位的hashcash,资源为foo,时间为111007(2011-10-07),salt为R1ecP62xhTg3vOu9,sha1的值为:

00000da561718af8f64802e0ee7ccea2efe54c39

前导零共20位(5个0×0表示的)。这便满足了第一条要求。

hashcash中的salt信息用于给用户以产生多个hashcash而不重复的空间。

我们再次理解一下这个技术。实际上,若将一个hashcash字符串标记在一个资源的请求上(比如发送电子邮件), 而这个字符串是经过验证而有效的,那么就意味着,发出这个请求的人确实花费了一点时间来计算这个字符串。 而根据资源提供者要求的位数,可以控制这个需要花费的时间。

对于20位的hashcash,PC上大约需要1s数量级或者更少一点来产生。 这对于提交资源等活动来说是微不足道的。但是对于垃圾邮件群发者或者密码暴力破解者, 每次花费1s将限制他们每天的活动次数在86400次附近(这是不能满足他们要求的速度)。

于是NERV认为,hashcash是阻止用户大量申请某些资源的一种方便而有效的途径。 相比之下,验证码在这里没有hashcash方便,盖因它需要传送图片,而且需要服务器花费时间和精力产生图片。