比特币(BTC) 属于 加密货币(crypto-currency),但其实并不是加密的。
区块链上的所有交易内容都是公开的,比如 账户地址、转账金额、交易记录、源代码 都是公开的。
比特币(BTC) 主要用了密码学的 哈希 和 签名两个功能。
哈希(Hash)
什么是哈希函数(Hash)?
1、哈希函数(Hash)又称为“散列”,简单理解为对某一事物的映射操作,即A -> Hash(A)
2、我们通常使用数组或者链表来存储元素,一旦存储的内容数量特别多,需要占用很大的空间,而且在查找某个元素是否存在的过程中,数组和链表都需要挨个循环比较,而通过 哈希 计算,可以大大减少比较次数。
举个例子:
现在有4个数字{2,5,9,13},需要查找13是否存在,如果用数组进行存储,需要写个循环遍历四次才能找到,时间复杂度为O(n);
但存储时先使用哈希函数,这里我随便用一个函数:H[key] = key % 3
则四个数{2,5,9,13}对应的哈希值为:
H[2] = 2 % 3 = 2
H[5] = 5 % 3 = 2
H[9] = 9 % 3 = 0
H[13] = 13 % 3 = 1
然后把它们存储到相应的位置,当要查找 13 时,只要先使用哈希函数计算它的位置,然后去那个位置查看是否存在就好了,本例中只需查找一次,时间复杂度为 O(1)。
但是有没有发现什么问题 ?
选用哈希函数计算哈希值时,可能不同的 key 会得到相同的结果,一个地址怎么存放多个数据呢?这就是碰撞(冲突),而解决碰撞(冲突)的方法有链接法(拉链法),开放定址法等。
Cryptographic hash function 加密哈希函数的性质:
1、collision resistence(抵制哈希碰撞)
作用:对一个message:m,求它的hash值:H(m),
这个hash值可以认为是这个 message 的 digest(摘要),用来检测对这个 message 的篡改。
举个例子:
我有一个很大的文件,把它存储在一个云存储服务器上,将来需要的时候再下回来,那怎么知道我以后下载的版本和当初上传的版本是一致的呢?
这就用到了hash函数的collision resistence性质:
在上传这个文件前,我先算一个哈希值买这个hash值存在本地,将来下载之后,我再算一个hash值,如果是一样的话,那么说明上传的文件没有被篡改过。
目前并不存在一个哈希(hash)函数可以从数学上证明具有collision resistance的性质。
从理论上是证不出来的,只能靠实践中的经验。有些哈希(hash)函数经过长期实践检验,都找不到人为制造哈希碰撞的方法,所以就认为这些哈希函数是collision resistence的。也有一些哈希函数以前被认为是collision resistence的,但找到了人为制造哈希碰撞的方法,比如:MD5,它曾经是一个很流行的哈希函数,但是现在我们已经知道如何去人为制造哈希碰撞了。
2、hiding
哈希函数的计算过程是单向的,是不可逆的。
给定一个 x,可以计算 x 的哈希值 H(x),但是从哈希值H(x),是无法反推出 x 的。也就是说哈希值H(x)没有泄露有关输入 x 的任何信息。
但是是不是一定不知道输入 x 的信息呢?
如果想知道输入的信息,可以用暴力求解的方法,把输入x所有可能的取值全部遍历一遍,看看输出的哪个哈希值和原来的哈希值相等,这样就可以猜出原来的输入是什么。
所以hiding这个性质成立的前提是输入的空间要非常的大,使得暴力求解是不可行的,而且输入的分布要比较均匀,各种取值的可能性都是差不多的。如果输入空间虽然也是非常大的,但是绝大多数情况下取值都是集中在少数的几个值,那么也是很容易被破解的。
hiding的性质有什么作用呢?
hiding 可以和 collision resistence 结合在一起,从而实现 digital commitment - 数字化委托,(有时也叫做 digital equivalent of a sealed envelope - 数字等效的密封信封)。
在现实生活中,sealed envelope 有什么用呢?
举个例子:
有一个人说他能预测第二天的股市,哪些股票会涨停。那如何证明他的预测是不是准确的呢?
一种办法是这个人前一天在电视台上公布预测结果,第二天看预测的结果是不是准确的。但是这样做会出现一个问题,提前公布预测结果的话可能会影响最终的结果,如果这个人很有名气,大家都很追捧信任,从而导致本来不会涨停的股票反而涨停了。所以预测的结果不能提前公开,而是把结果写到一张纸上,用信封封好并交给第三方的公证机构保管,等到实际结果出现后开启密封进行对比。
在电子世界里,区块链技术也同样提供了一个好的解决方法:把预测结果作为输入 x,算出一个哈希值H(x),把这个哈希值H(x)公布出去,因为有hiding的性质,所以从哈希值H(x)是不知道x的。 等到预测结果发生时间来临后,公布x,如果根据 x 可以得到公布的Hash(x),则说明预测正确。
在实际使用时,为了 x 能够足够大并且足够均匀,会在 x 的后面随机拼接一个 随机数nonce,对其整体取Hash。
3、 Puzzle friendly
除了密码学中需要的这两个性质,比特币系统中还需要第三个性质:Puzzle friendly。
该性质要求哈希值的计算事先不可预测。即单纯看输入,是很难猜到最后的哈希值是什么。所以如果你想要算出来的哈希值是落在某个范围之内的,那只能一个一个输入去试,看哪一个输入算出来恰好是落在那个范围之内。
举个例子:
比特币“挖矿”。“挖矿”实际就是找随机数,这个随机数跟区块的块头里的其他信息合在一起作为输入,取出一个哈希来,哈希值要小于等于某个指定的目标阈值 。
即 H(block header) <= target
区块链是一个一个区块组成的链表,每个区块有一个块头(block header),块头里面有很多的阈,其中有一个阈是我们可以设置的随机数,那么挖矿的过程就是不停地去试各种随机数,使得整个 block header 取哈希之后落在指定的范围内。
挖矿的过程没有捷径,只能不停地试大量的随机数,才能找到符合要求的解,所以这个过程用来作为工作量证明(POW - Proof Of Work)。
虽然挖矿的过程需要很多的工作量才能找到一个符合要求的随机数,但只要有人找到这样的随机数,发布出去之后,其他人验证这个随机数符不符合要求是很容易的,因为这个随机数作为区块的一部分,只要算一次哈希值,看是否是小于等于目标阈值即可。所以挖矿很难,但是验证容易。
在比特币系统中采用的哈希函数是 SHA-256 (Secure Hash Algorithm)
签名
比特币系统中的账户管理
日常生活中如果要想开一个账户,你会带上证件去银行办理开户手续,这就是中心化账户管理系统方式。
而比特币是去中心化的,它没有银行之类的机构,所以每个用户自己决定开户,不需要任何人批准,开户的过程很简单,就是创立一个公钥和私钥的对(public key,private key)
公钥和私钥的概念来源于非对称的加密体系(asymmetric encryption algorithm),
最早的体系是对称的加密体系(symmetric encryption algorithm)。
比如:
两个人之间要进行通讯,我要把某个信息发给你,但是通讯的网路是有可能被窃听的,那我们两个人事先会商量好一个密钥(encyption key),我把信息加密之后再发给你,你收到之后再用密钥解密,因为加密和解密用的是同一个密钥,所以叫对称的加密体系。
但是对称加密体系的密钥不可以以明文的形式公布出来,所以非对称的加密体系就使用了一对密钥,而不是一个密钥。加密用的是公钥,解密用的是私钥。比如我要把一个信息传给你,我用你的公钥对其加密,你收到后,再用你的私钥解密。这样的话,公钥是不用保密的,可以对外公开,私钥只需保存在本地即可,不需要传给其他人,这就解决了对称加密体系中密钥分发不方便的问题。
比特币系统中,如果要创建一个账户,就在本地产生一对公钥和私钥,公钥就相当于银行卡号,别人给你转账,只需知道你的公钥,私钥相当于账户密码,知道私钥就可以把账户的钱转走。
问题:一开始说比特币系统是不加密的,信息都是公开的,那要公钥和私钥干什么?
实际就是用来做 签名。
比如:
我要转10个比特币给你,然后我把交易发送到区块链上,别人怎么知道这个交易确实是我发起的呢?这就需要我在发布这个交易的时候,需要用私钥对这个交易签名,其他人收到这个交易之后,再用我的公钥去验证这个签名的正确性。
问题:每个人的公钥和私钥是独立产生的,那么万一两个人生成的公钥私钥恰好相同怎么办?比如一个人想偷取比特币,不停地去产生大量的公私钥,然后对比一下产生的公钥跟区块链上某个已有的公钥是不是相同,如果是一样的话,就用对应的私钥把账上的钱偷走。
这种攻击方式从理论上说是可以的,但是实际中是不可行的,因为256位的哈希值产生相同的公钥私钥的可能性是微乎其微的,概率比地球爆炸的概率还要小,并且从来没有这种先例。