写在前面
写这篇文章的动机,缘于一次对比特币原理科普性质的分享。讲的过程中发现,想把比特币真正讲明白,是非常困难的。所以决定把分享的内容记录下来,也力求把比特币这一新事物讲清楚。对于比特币中用到很多专业技术,我也尽量用通俗的说法来解释。如果最后没能达到目的,就权当是自己的一次总结了吧。
最原始的比特币模型
从最简单的角度看,比特币的功能有点类似银行或者支付宝这类支付机构,它为每个账户记录了余额,并且提供了让大家相互转帐的功能。
在没有比特币之前,我们的支付机构是怎么做的呢?
- 如果A想给B转帐,他会把这条消息发送给支付机构
-
支付机构对二人账户的余额进行调整,并且作为见证人,对二人间的这一交易行为提供保证。
然而在一些场景下,我们并不想要这样的一个“支付机构”。比如:
- 涉及到跨国的转账时,双方可能会因为互不信任而不愿使用任何一国的支付机构;
- 两个犯罪分子要进行一些非法买卖,通过银行转账会有被拦截交易和冻结账号的风险。
尽管这两个例子稍嫌极端,但它们仍旧提出了一个技术上非常务实的问题:“假如不依赖任何一个中介机构,构建在互联网上的转账系统是可行的吗?”
面对这一问题,许多先辈进行了不懈的努力。在2009年,随着比特币系统横空出世,这一问题总算才有了一个可行的解决方案。
那么比特币究竟是怎么解决这一问题的呢?概括来说,它的思路如下:
- 如果要通过网络转账,那么“公立的、转账双方都认可的第三方账本”是绝对不可避免的。
- 既然“第三方账本”不能由某一个机构来提供,那么就只能由广大的人群来作为一个整体提供。
将“人群集体提供账本”这一想法展开,就可以勾勒出最雏形的比特币转账过程来:
- A给B转账时,要在人群中大喊一声“我是A,我要给B转10块钱”;
- 众人在听到A的消息时,会在各自的账本上记录这笔交易,并各自对A和B的余额做相应的调整;
-
对B而言呢,他会向人群确认,如果大家都认同这笔交易,那么B就会认可这次转账行为。
那么这样的一种转账模型意味着什么呢?如果和纸币对比一下,我们更能看出比特币系统的不同来:
- 对于纸币,所有拿在你手里的钱都属于你自己,不需要任何人证明。转账过程也相当简单:把你手里的钱给别人就行了。
- 对于银行的数字资产,所有记在你银行账户的资产都属于你,你有多少钱银行说了算。转账过程由银行来操作。
- 而对于比特币,你有多少钱,以及你有没有给别人转过账,是由别人的账本共同说了算的。这也就意味着,人群手上的账本都维持一致是非常重要的。
另外需要强调的是,上面在描述转账时,用的是“人群”和“大喊”这样的方式来类比的。在真正的比特币网络中,这两种方式都是不存在的。所谓人群,其实是运行在世界各地的计算机节点;而所谓“人手一份的账本”,也是记录在计算机节点之上的电子文件;而“大喊”,则是对“利用互联网传播消息”的一种形象描述。在本文后面的内容中,这种比喻的形式仍旧会不时的出现,大家读到时,一定要对应到真正的计算机世界中去。
困难在哪里
在上面我们提到的模型中,有几个非常致命的问题必须得正视:
- 转账发起方的身份认证:当人群收到A的付款消息时,怎么确定是A本人发出的,而不是别人假冒的。
- 如何维持人群中每个记账人账本的一致,这点在前面也强调过。这种一致性体现在两个方面:每个人账户余额的一致和转账行为的一致。
对于保持一致的问题,重要性是不言而喻的。但初看一下,似乎也没有那么难:“A给B转10块,大家听到A的消息后,一起修改账本就行了嘛。”
但事实却是,这一问题的复杂程度,远非这句轻描淡写的“一起修改账本”可以概括。根本原因就在于,消息广播和记录都是发生在互联网世界的计算机节点上的。例如:
- 可能只有部分节点收到了A的广播,其他节点因为网络或者自身原因错失了这条信息
- 如果A账上只有10块钱,他向一部分节点声称给B转10块,再向另一部分声称给C转10块。大家在记账时怎么保证只有一笔成功?
- 如果有一部分节点故意不记账怎么办,篡改交易记录又怎么办?
账本“一致性”的问题,上面我也只大致给了一部分场景。在真正实现和部署这样的一个计算机系统时,遇到的问题和挑战只会更多。概括来说的话,分布在世界各地的计算机节点对这样一个“账本”的一致性问题一般会分成两类:
- 假设所有的节点都是诚信善良的。在这样的前提下,设计系统一般考虑的问题就是消息传输时的丢失、乱序,以及某个节点的停止服务(停电、关机、网络欠费、网线坏掉)等。
- 假设有一些节点会从中作梗。这里面就包括对消息的篡改、无视、伪造、以讹传讹等等。在业内,大家一般用“拜占庭错误”这一行话来指代这类问题。相应的,能容忍这类问题的系统,也被叫做“拜占庭容错”的系统。
此外,把“担保交给人群”的比特币系统还会有第三个问题:隐私性。因为人手一份账本,所以各个账户下余额多少自然是尽人皆知了。虽然和账户安全的问题比起来,这似乎并不算个事儿。可真正开了户后,我相信有钱人还是更喜欢低调做人的:-)
总的来看,对于比特币的模型,会有三类问题摆在系统设计者的面前:
- 身份认证
- 拜占庭容错的一致性(在其他一些资料中,会把这一问题叫做“共识问题”,相应的解决方案叫“共识机制”);以及在这种情况下,收发双方如何确认交易已完成。
- 隐私性
身份认证
上面的几个问题中,身份认证是最容易解决的。就像我们平常用签名字迹来辨识人一样;在比特币系统中,我们通过“数字签名”来确认消息发起方的真伪。和字迹所不同的是,“数字签名”更可靠,更难以被伪造。
如果想真正弄明白数字签名的原理,需要涉及到一些数论和抽象代数的知识。作为一个科普性质的文章,我觉得还是很有义务把这些艰深的知识扔到一边的(虽然真正的原因,是我对这些知识也一知半解)。但既然科普的牛皮已经吹出去了,不管怎样还是得像模像样的找个例子来解释下的。
在我的例子里,我们需要首先把自己的数学水平下拉到三年级左右的层次。在这样的水平下,我们能读、写、理解很大的数字,也会做位数比较高的乘法,而对于最简单的除法,我们都没有任何概念。
那么,在这样的一个前提下,面对这样的计算任务:
31 × 32 = ?
我们能很快计算出结果992;而对于这样的计算任务:
? × 32 = 992
我们就近乎无能为力了。
如果每个人都只有三年级的数学水平,那么A就可以充分利用这一点进行转帐了:
- 首先,在转账前他会生成这样的一对算式:31 × 32 = 992
- 然后,他会通过各种渠道把(32, 992)这对数字告诉大家,而把31牢牢记在自己的心里。众人皆知的(32, 992)叫做公钥,而自己守口如瓶的31叫私钥。
- 假如他要给别人转账15块,他会把转账金额15广播出去。与之相对应,他还会把15和私钥31的乘积465也一起广播出去。而465,就叫A对转账金额15的数字签名。所以最后的发出的消息就是:转帐者A,金额15,签名465
- 为什么把465叫做签名呢?首先,465是A拿私钥31计算出来的。而别人拿到(金额15, 签名465)这一消息后,可以利用A的公钥(32, 992)进行校验:大家会计算15 × 992和32 × 465的结果是否相同。如果相同,就说明消息是A发的;否则,消息是伪造的。
- 换句话说,任何的转账消息都是“转账人,金额,签名”这种格式,收到交易消息的记账人,会依据转账人的公钥对签名按照公开的计算规则进行验证,如果验证通过,才认可这笔交易。
形式化一下上面的过程就是:
- 转账者生成一对数字(a, b), 并计算:a × b = sum
- 转账者牢记私钥a, 并公开公钥(b, sum)
- 交易时,A广播本次交易金额d和签名sig,sig由a和d相乘所得。
- 分散在世界各地的记账者,每收到转账消息(转账人A, 额度d, 签名sig)时,会拿A的公钥(b, sum)校验消息。如果和sig × b = d × sum,则确认消息是A本人发的;反之则认定这是一条伪造的消息。
这个验证过程为什么可行,也可以简单总结下了:
- A虽然没有透露自己的密码a,但通过(b, sum),暗示出了自己的身份是能乘以b等于sum的那个人。但别人不会计算除法,所以哪怕看着b和sum, 也不知道a到底是多少
- 在收到d和签名乘积sig后,记账人就可以想:既然发消息的这个人说自己是A,那么乘积sig一定是用他的a和余额d相乘算出来的;我手头已经有(b, sum)了,简单验证下sig/d 和sum/b是不是一样就行了嘛。除法我是不会算的,那么只好变通下,检验sig × b = sum × d也可以。
- 一个伪造者想要仿冒A的身份,只能尝试把a找出来。由于不会计算除法,想寻找a也只能从1开始挨个试了,直到试出一个数字乘以b等于sum为止。如果我们把a从整数扩充到小数,位数也调到非常高。挨个试的成本也会陡增而甚至变得不可能了。
好,例子举完了。虽然和真正的数字签名谬以千里,但讲解其中的概念也足够了。概括来说,在数字签名中涉及的技术理念有如下这些:
- 利用一种计算体系中正向和逆向计算的难度不同
- 对一些计算过程做部分公开,公开的部分叫公钥,保持私密的部分叫私钥。消息发送者本人用私钥对消息进行签名。任何人都可以用公钥对消息进行验证。
- 伪造者获取私钥后才可以伪造消息。如果不考虑其他坑蒙拐骗的手段,获取私钥唯一的好方法就是挨个对私钥进行猜测。而这一过程所耗费的时间非常恐怖。就现在人类的知识体系和计算力而言,几乎可以认为是不可能的。
把数字签名的技术应用到比特币系统中后,公钥就对应着我们的的账户地址,对所有人是公开可见的;而私钥则是我们的账户密码,只有我们自己知道。当给别人转账时,我们会拿密码来签名我们的转账消息,并且指定别人的账户地址。而别人想再次把这笔收到的款项转给别人时,也只有提供的出对应的签名才行。
所以最后总结一下,一笔转账交易的几个重要部分如下:
- 付款方的公钥,标记付款账户
- 收款人的公钥,标记收款账户
- 交易金额
- 付款人用私钥对这笔交易的签名
虽然数字签名这一技术要比比特币本身古老得多,但把这一技术应用到这种非中心式的账本体系中时,我们仍能看到它和银行有多么的不同。在有银行的世界里,我们是完全相信银行的。去银行开通账号和设置密码后,我们个人和银行之间就分享了一个小秘密;在每次交易前,银行也通过验证这个共同的秘密来认证我们的身份。这颇有一点各种谍战剧中接头暗号的味道,整个过程所利用的,是交易参与者和攻击者之间信息上的不对称。而数字签名的交易过程则完全不同。除了交易发起者之外,身份验证方和攻击者之间拥有的信息是完全相同的。整个过程利用的,是签名交易和认证交易在计算上的不对称。
这种形式上的转变,使得我们不用再信任其他的第三方机构,似乎非常美好。但坏处也显而易见:一旦私钥丢失了,想拿着自己的身份证去重置密码就是不可能的了。因为在整个交易环节中,除了私钥产生的签名,我们没有任何的手段可以证明“我就是我”;那个和私钥所匹配的公钥,既不是姓名,也不是身份证号,也不是住址,而是一串恰好和别人不一样的数字而已。更进一步看,一旦私钥泄露了出去,我们也不可能指望银行和公安机关来帮忙冻结交易以及追回损失了。
说到这里,你也许会认为比特币这种技术实在太过“冷冰冰”。但从另一个角度而言,这完全是“求仁得仁”:放弃了对第三方机构的信赖,也就得放弃这种信赖可能带来的好处。