去中心化的账本还是很容易理解的,只要把所有的交易记录都记在每一台电脑的账本上,然后就可以用计算机的强大计算能力,随时随地查出每个人的余额是多少。
但是大家不要忘了,在网络上记账与线下记账不同。网络上都是消息来消息去的,大家根本不见面。如果你收到一条信息,上面写着“A支付5元钱给B”。这时,你不禁要问:
第一,如何确保这条信息内容的完整性?第二,如何确保信息的真实性?这两个问题不解决,去中心化账本的理想就无法实现。解决办法是有的。我们先来看怎么解决第一个问题:确保记账信息的完整性。
这里要引入一个概念,就是数字指纹(很多文章中也叫数字签名、哈希值)。电脑上的任何信息,按照国际统一的编码标准,最终都是以0和1来存储,这就是大名鼎鼎的二进制。例如“钱”这个字用二进制表示就是“1001010010110001”,再比如“A支付5元钱给B”这句话,用二进制表示就是:
0100000111001010010111110011101101100000110101101000101000011100101001011000111111101101100101000010
普通人看到二进制往往无法和数字建立联系,实际上,这串二进制数字也可以用一组十进制的数字来表示,它们完全相等:
100000111001010080606408664086260086008422488464406842602666664446622202242228042826680682422068400
看到了十进制的数,很多人才会认为这确实是一个“数字”。这就是数字指纹了吗?还不是。
二进制和原始信息只是一一对应的编码关系,一个英文字母或者数字对应8个比特,一个中文字符对应16比特,原始信息越长,二进制编码也越长。任何原始信息都可以转换成一串数字,有了数字就可以做数学运算,玩出各种花样了。
现在,我们给数学家提出一个要求:请设计一个算法,将任何一条信息,不论长短,都计算出一个唯一的“数字指纹”与它对应。但有两个附加条件:一、指纹的长度必须固定;二、只能从“原始信息”计算出“指纹”,谁也无法从“指纹”反向计算出“原始信息”。
这个要求,看似很过分,但是难不倒数学家。1993年,美国国家安全局发布了SHA算法,全称是Secure Hash Algorithm,中文一般翻译为“安全散列算法”或者“安全哈希算法”,这个名称估计把你吓到了,听着特学术(我有时候会听人说“嘻哈算法”,忍不住偷笑一下,各位千万别读错)。
Hash这个词没有对应的中文意译词,如果让我来意译的话,我会翻译为“数字摘要算法”,基本上能表达该算法的含义,就是从目标对象中提取出一个特征摘要,好像人的指纹一样。
SHA算法从1993年发布它的第零代,一直到2015年发布第三代,二十二年间已经升级了四次。比特币用到的是第二代算法,简称为SHA-256算法,这里的“256”表示,由这个算法生成的指纹长度固定为256比特。大家可以很容易在网上找到在线生成SHA-256指纹的网页,这个算法是公开的,谁都能用,例如,“钱”字的SHA-256指纹是:
0000111010111000011000111100011110001101101000111110001110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
“A支付5元钱给B”的SHA-256指纹是:
1111011110111011001010011011101011011111000001011101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
大家看到,不论原始信息有多长,生成的指纹都是一样长的。而且这个指纹还有两个显著特点:一、原始信息只要改变一点点,哪怕只改动一个数字,整个指纹就会发生巨大的变化,毫无规律可循;二、截至本文写作时,世界上还没有任何公开的方法可以从指纹反向计算出原始信息,普遍认为理论上无法破解。
不过,在实际的使用中,256位的二进制数据太长了,使用起来极不方便,还很容易看花眼。于是,指纹通常用十六进制来显示,反正二进制到十六进制是一一对应的。
“钱”的十六进制指纹是:
0eb863c78da3e38b6b92d1f3999566e5d8e17a6f700a112c8993cf6bfc48f70b
“A支付5元钱给B”的十六进制指纹是:
f7bb29badf05d41e60b1036d749f134a901c7a97daef7a1fe4e1e14471bd4833
这样看起来就简洁多了,我们可以试一下把“5元钱”改为“6元钱”,看看指纹的变化有多大,下面是改后的指纹:
1d48da12b0fb29efe6f690185922f96d259bd887343735898bfc3901a83b58c3
看到了吧,仅仅改动了一个数字,但指纹几乎没有一位是相同的。这就是SHA算法的神奇之处,也确保了指纹没有规律可循,无法被反向破译。
有了数字指纹,就可以解决第一个问题:确保记账信息的完整性。怎么做?很简单,我们只要做出一个规定,任何发出信息的一方,必须同时发出原始信息的指纹。
那么收到信息的一方只需要用公开的SHA-256算法把原始信息也生成一个指纹,和收到的指纹比对一下,如果一致,就说明收到的信息是完整的;如果不一致,说明收到的原始信息由于某种原因被修改过了,这个原因可能是数据传输过程中的错误,也可能是被人篡改了等等。
那会不会有一种巧合,原始信息和指纹都因为某些传输错误发生了改变,恰好错误的指纹数据就是出错后的原始信息指纹,也就是负负得正了?这事当然不是绝对的不可能,但是从概率上来说,想要自然发生,大概等到宇宙灭亡了也不会发生一次,概率已经低到可以彻底忽略。
不过,你可能也想到了,还有一种可能性,就是黑客恶意篡改。因为SHA算法是公开的,如果有一个黑客拦截了原始信息和指纹,他把原始信息修改掉,比如把“A支付5元钱给B”改为“A支付5元钱给C”,同时生成新的指纹发送给你。
这该怎么办呢?这就是我们要解决的第二个问题:如何确保信息的真实性?解决这个问题,等于也解决了信息发送方想抵赖的问题。
解决第二个问题的关键就是给指纹加密,但是,这种加密还不能是我们在谍战剧里看到的那种电报加密的方式。
大家不妨回忆一下看过的谍战剧,我地下工作者收到一封电报,上面写着2352,于是他从书架上拿出一本书,翻到第23页,再数到第52个字,写着一个“撤”字。这就是组织上通知这位同志马上撤退,有人叛变了。
这种加密方式的坏处在于,只要敌人也掌握了密码本,不但可以破译电报,还能发送假电报钓鱼,原因就在于加密和解密的方法是完全一样的,能解密就能加密,所以,这种加密方法被叫作“对称加密”,解密的过程只不过是加密的逆过程而已。
“对称加密”用在我们想要的去中心化账本系统中就不好使了,因为我们既要让网络上的每一个信息接收者能够解开密文知道原始信息,又要让黑客即使拿到密文也只能干瞪眼,无法篡改密文。
个中关键,在于加密和解密的方法必须不一样。所以,就要求数学家搞出一种全新的加密算法,这种算法是非对称的,加密、解密不是互逆的过程。
能不能搞出这样一个巧妙的加密算法呢?当然是能的,否则就不会有比特币了嘛。下面我用一个简化版的非对称加密算法模拟一下我们想实现的效果。
原始信息是一组数字:269。
现在,我用一种只有我自己才知道的加密算法得到一个密文:24479。
然后,我把24479告诉所有人的同时,还宣布:解开我这条密文的钥匙就是数字11(后面我们就把这个公开的钥匙称为公钥),任何人只要用24479乘以11,取结果的后三位,就能得到我想要告诉大家的原始信息。不信吗?我们试试看:
24479×11=269269
哇,好有意思,不单后三位,连前三位都是原始信息。我是怎么加密的呢?很简单,我把原始信息乘以91就是密文,而这个91就可以叫“私钥”,我私人的加密钥匙。这样就实现了加密和解密是完全不一样的两种算法。
你可以试试看,用任意一个三位数字乘以91,得到的结果再乘以11,最终得到的结果一定是原始三位数写两遍。例如:218×91×11=218218。
如果用任意一个二位数字乘以91,得到的结果再乘以11,最终得到的结果后二位数字也一定与原始数字相同。例如:18×91×11=18018,至于它背后的数学原理,稍微琢磨一下就能想明白了。
但是请记住,我举的这个例子只是让你体会一下什么叫非对称加密,因为这个例子的算法太过简单,所以知道了公钥是11的人,很容易猜出私钥是91。
但是比特币系统采用的算法比这个复杂多了,那个算法确保了任何人即使知道原文、密文、公钥,也无法猜到私钥。也就是说,黑客只能解密,但不会加密,无法修改密文。
这么牛的算法,就是声名远播的“椭圆曲线算法”,简称为ECC算法。
它是在1985年由两位美国人尼尔·库伯利兹(Neal Koblitz)和维克托·米勒(Victor Miller)分别独立提出的。在密码学中的广泛使用,也就是最近十多年的时间,数学家真的很厉害。
有了这个算法,就能确保去中心化的记账系统中,每条交易记录的真实性。
我们来演示一下比特币的去中心化记账系统如何利用SHA和ECC算法确保账本的完整性和真实性(以下是简化后的原理说明,真实过程还要复杂很多,但原理不变)。
需要记账的原始交易信息:A支付5元钱给B(以下简称“原文”)。
第一步:利用SHA将原文生成数字指纹:
f7bb29badf05d41e60b1036d749f134a901c7a97daef7a1fe4e1e14471bd4833
第二步:随机生成一个私钥,它的格式与指纹是完全一样的,例如:
18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725
第三步:利用ECC将第一步得到的数字指纹通过私钥加密,得到密文:
869ac57b83ccf75ca9da8895823562fffb611e3c297d9c2d4612aeeb32850078
第四步:根据私钥生成一个公钥:
600FFE422B4E00731A59557A5CCA46CC183944191006324A447BDB2D98D4B408
第五步:将原文、密文和公钥广播到整个比特币网络中。信息发送步骤到此结束,以下是信息接收步骤。
第六步:接收方利用ECC将密文通过公钥解密,得到指纹1。
第七步:利用SHA将原文生成数字指纹,得到指纹2。
第八步:比对指纹1是否等于指纹2。
第九步:如果相等,则确认该条信息是合法交易信息,添加到自己的账本中。如果不相等,则抛弃该信息。至此全部结束。在真实的比特币网络中,交易双方都是完全匿名的,交易者A或者B都是账号(有些文章中称“地址”,含义一样),账号背后的主人信息是没有任何记录的,可以是一条狗,也可以是一个人工智能,而账号则是根据公钥,通过一定的算法生成的。
一个私钥几乎可以生成无数个不同的对应公钥,也就意味着可以生成几乎无数个不同的对应账号。谁掌握了私钥,谁就是账号的主人。
在比特币网络中,私钥是动用账号中比特币的唯一凭证,如果你的私钥被盗,你就永远失去了它,打官司也要不回来,因为没有任何方式可以证明他的私钥是从你这里偷走的。
比特币原理深入
区块链技术