比特币“工作量证明”鼻祖——hashcash 算法
比特币的架构,在技术上可谓是集大成于一家。比如分布式系统、去中心化、非对称加密、工作量证明等等。
本篇聊聊最早提出的工作量证明的应用——hashcash,有翻译:比特币现金,本文还是沿用原名hashcash。
而它最早构想,是应用在电子邮件内,用于防止垃圾邮件的一个机制。
而比特币的工作量证明,基本就是借鉴了这个思路。
垃圾邮件的泛滥
虽然现在国内,即时聊天(如QQ、微信)大大取代了电子邮件,但是在“万恶的资本主义”世界内,电子邮件还是最受青睐的一个通讯工具。
在早期,即时聊天还没有诞生的时候,电子邮件更是最重要的点对点通信工具。电子邮件作为主要的通讯工具,自然是营销人员最喜爱的推广工具。
只要知道对方邮箱便可往对方邮箱塞东西了,架一个脚本,搞个电子邮件的群发、盲发、批量并发营销邮件——也就是垃圾邮件,这对于电子邮件发送方来说,基本是毫无代价的。
而在接受方,垃圾邮件就是人们非常头痛的一个事情了:它常常可以把正常的邮件冲得“落花流水春去也”。
让发邮件有代价:工作量证明
电子邮件,没有邮票这一说,否则,要求发邮件贴几分钱邮票,垃圾邮件都没有那么猖狂了。
于是,一些技术大牛就会想:有没有一种办法,让邮件发送方需要付出一些代价才可以发送一封邮件,而接收方可简单的验证邮件是否是合法的?
牛人Adam Back的一篇论文《Hashcash – A Denial of Service Counter-Measure》(连接文章末尾),于1997年首次提出。
Hashcash 的做法就是这样:要求发给我的电子邮件header中包含一个stamp(戳记),这个标记需要进行大量计算才可生成,格式如下:
也就是说,所有发送给我的邮件,需要带上一个这样的X-Hashcash(也就是前面的stamp),需要满足:
1 sha-1(X-hashcash) 的前面0的个数,大于X-hashcash.bits 的值(比如20);
2 X-hashcash.date 和当前时间不能超过2天(主要是为了防止服务器之间时间差异或者网络延时);
3 X-hashcash.resource 指明是我的电子邮箱(或者其他如IP、URI);
4 每个X-hashcash 只能用一次(我会记录以前是否有使用过该值)。
我们看一个合法的stamp:
X-Hashcash: 1:20:13030X30600:adam@cypherspace.org::McMybZIhxKXu57jd:ckvi
我们先来构建代码看看,如果要发送邮件给 10001@gamil.com,bits为20,我们测试下计算一个X-hashcash 需要的时间,代码:
from time import strftime, localtime, time
from math import ceil, floor
import hashlib
def _mint(challenge, bits):
hex_digits = int(ceil(bits/4.))
zeros = '0'*hex_digits
end_chars = ""
counter = 0
while 1:
end_chars = hex(counter)[2:]
digest = hashlib.sha1((challenge+end_chars).encode()).hexdigest()
if digest[:hex_digits] == zeros:
print("运算了:%d 次!" % counter)
return end_chars
counter += 1
def mint(resource, bits, ext, salt):
ts = strftime("%y%m%d%H%M%S", localtime(time()))
ver = "1"
challenge = "%s:"*6 % (ver, bits, ts, resource, ext, salt)
return challenge + _mint(challenge, bits)
start = time() * 1000
# 偷懒,写死salt为 "1QTjaYd7niiQA/sc"
x_hashcash = mint("10001@gamil.com", 20, "", "1QTjaYd7niiQA/sc")
end = time() * 1000
print("用时:%d ms, \nX-hashcash:" % int(end - start))
print(x_hashcash)
执行结果:
如上测试代码,发送方构造一个邮件X-hashcash头,在要求bits为20情况下,计算了1541662次hash值,用时是2351毫秒(2.3秒),bits 可随着硬件提升而可约定增加。
如何抵制了垃圾邮件?
1)垃圾邮件发送方
由于没有很方便的计算符合条件的X-hashcash的方法,所以,只有如上代码那样,进行枚举一个一个地算其hash值,直到逮到一个满足条件的值为止。这个是非常耗算力的。前面文章提到过《一分钟了解,比特币知识,为什么比特币挖矿那么费电》也是一样意思。
但对于垃圾邮件来说,他们期望发送邮件,是海量的发送的,数十甚至上百封邮件一秒。由于需要计算大量的X-hashcash,其垃圾邮件效果就大大受挫了。达到抵制垃圾邮件内容的效果。
2)对于正常邮件发送方
这个计算时间对于正常的邮件发送者,是可以接受的,因为填好邮件接收方,计算机便可开始计算X-hashcash 头了,邮件编辑者同时可以编辑邮件内容。就算是数秒的计算可以说无所谓。
3)对于邮件接收方
而对于邮件接收方来说,验证其hash值是非常方便的,验证X-hashcash都不用1毫秒(用前面的:1541662次hash值,用时是2351毫秒,0.0015ms)不管bits调整到多少位,验证时间都是几乎不变。
也就是引入hashcash的系统,正常的邮件发送方和接受方,都没有太大的成本,但对于垃圾邮件发送者来说,大量的计算会“劝退”一大帮了。
最成功的应用:比特币
目前为止,hashcash的最成功应用,就数比特币了,比特币使用类似hashcash算法来作为矿工的工作量证明。
中本聪也没有照搬hashcash,而做了调整:
* 使用了强度更好的sha256(256位)代替sha1(160位);
* 为了更好的安全性,中本聪是hash运行了两次;
* hashcash中的bits 在比特币中,使用了共识周期性动态调整,使得区块创建率不变(10分钟出块)。
hashcash 的缺点
毫无疑问,和比特币一样,其缺点就是浪费cup算力了,只是对于正常的某个邮件发送方来说,这单算力是可以不计较,但是全球亿计的正常邮件在传输,这个算力总体来说,就是一个浪费了。
参考资料:
David Mertz, Ph.D.实现的Python版本的hashcash:
http://www.gnosis.cx/download/gnosis/util/hashcash.py
wiki百科:
https://en.wikipedia.org/wiki/Hashcash
Hashcash – A Denial of Service Counter-Measure:
http://www.hashcash.org/papers/hashcash.pdf
(全文完)
(欢迎转载本站文章,但请注明作者和出处 云域 – Yuccn )