当前位置:首页 > 区块链资讯 > 技术教程

谈比特币签名原理:深入浅出比特币签名

比特币的交易就是如下形式的汇款单,一半是付款信息,给出付款签名和公章,另一半是收款信息,给出金额,目标地址和兑现方式

深入浅出比特币签名 (1)

对各个会计(全节点)来说,接收到这张汇款单时,有两个最重要的安全问题:

第一,如何保证这张汇款单不是假的?

第二,如何保证汇款单上的签名不是假的?

事实上,比特币里第一个问题是保证不了的,也即如果两张不同的汇款单的签名都符合要求,你不知道哪个是真的,这就是大名鼎鼎的据说导致了MTGOX倒闭的交易延展性问题(transaction malleability)

不过,交易一旦确认,也就是记录到账簿以后,付款账户就是空的了(比特币每次都是将一个地址中所有的币都花掉),所以从已确认交易的角度来说,不可能出现重复花一个地址的币的交易,这两张汇款单中必然有一张最后要报废

为什么会出现两张不同的汇款单都有效的情况?这是比特币目前设计上的一个缺陷,是一个历史遗留问题,在我下一篇文章中进一步讨论到签名细节的时候,就可以明白为什么了。但现在先看第二个问题,也即签名的安全保证,只有先搞明白这个,才可以回答第一个问题

签名简单比喻来说就是盖章

比特币中用了一种方法:刻一个章摔成两半,一半私用,一半公用,私用的一半自己留着用于交易的时候盖,而公用的那一半章(公钥)则在交易时付款信息里盖在空白处并随汇款单发送。公章里暗含有我要花的币的地址(下面有述)。这样,收到汇款单的人只要看到我发布的那一半公章(公钥),就可以验证是否符合我要花的币的地址,并且可以用来和我盖的那一半私章对比,如果中间的裂缝在显微镜下也完美吻合,就证明私章是我盖的无疑,但他们却拿不到我的那一半私章(私章盖在文字上以后有很多部分和文字重叠而无法辨认了,无法仿造出来),这样我不担心有人会拿着我发布的那一半公章来假冒我授权的交易

当然,也可能会有解密高手(量子计算机)试图就我发布的公章而假造一个每个裂缝都与之完美吻合的私章(也就是通常所说的破解ECDSA椭圆曲线加密)。但如果我不花币,也就不用发送交易,那么别人光知道我的地址,却不知道公章是什么样子的,也就无从破解(公钥可以推出地址,有地址却不能推出公钥)

为什么知道地址却算不出公章呢?因为地址是通过计算公章里所有字的总笔画数产生(哈希算法)。可以想象:假设一个公章包含几百个字,光知道所有笔画的总数是完全无法知道公章是什么样子的,而有了公章却可以轻松验证这个总数是否符合。而这个总数就是比特币中的地址 (这只是个简化的例子,实际的哈希算法要复杂的多,不是算总长度,但原理类似,都是对某串文字算出一个唯一的数)

1.jpeg

之前说过,比特币转账每次都是彻底把原来账户中的币全部转走,因此只要我不重复使用同一个章,用完就扔掉,就不用担心别人拿到我的公章后能干啥:如果高手不能很快的在我发布交易后根据里面的公章算出私章,一旦交易完成,公章对应的就是一个空账户了

这就是为什么资深比特币玩家总是建议大家不要重复用同一地址,这是系统安全的最高级保障,有了这一点,即使量子计算机出现,比特币的交易也是安全的

了解盖章和数总笔画数这两个概念后,就能理解比特币如何保证签名的正确性了:首先,地址就是公章里包含的总笔画数,如果总笔画数和公章对不上,公章就是无效的,通过这个办法可以保证公章的有效性。其次,公章只是一个章的一半,如果公章和私章的合缝对不上,仍然是无效的

联系上面那幅图,再看交易就好理解多了

交易甲

付款信息:签名 公钥A

收款信息:0.9999 59 (地址B) 兑现条件

交易乙

付款信息:签名 公钥B

收款信息:0.9998 地址C 兑现条件

整个过程是:乙自己刻一个章B,摔成两半,一半是私章(私钥)B,一半是公章(公钥)B,然后他数了数公章B里包含的总笔画数,得出个数字59,也就是地址B,然后他把这个数字告诉甲,让甲给他发0.9999个币

于是甲发布了交易甲,收款信息里按照乙给他的地址59填入,兑现条件里写明按标准盖章方式验证。随后交易甲被会计审核通过,比特币总账簿里就记录了这笔交易,大家都可以查区块链看到,地址59 包含0.9999个币的余额

可见,要查地址B有多少币,是通过查交易甲的收款信息而查到的。含有币的地址叫UTXO,也即unspent output(未花交易)。在比特币中凡见到UTXO,就知道是指含有资金的地址信息,也是一串交易的最终一站

随后,乙想要花这个币的时候(交易乙),他就在交易乙的付款信息里空白处盖上地址B的公章,并另外写一串数(这串数后面解释),并在这串数上盖上他的私章

交易乙

付款信息:一串数上盖私章(签名) 公章B (公钥B)

收款信息:0.9998 地址C 兑现条件

公章B里的总笔画长度是59,和地址B相同,可证明乙是地址B的公章拥有者,然后乙在那串数上盖的私章的裂缝和公章又完全吻合(会计通过把他发布的公章盖回到那串数上,以验证两者之间的裂缝是否完全吻合),证明他的公章是他自己的,这样比特币中的付款安全验证就完整了

1.jpeg

总结一下:由地址不能得到公章,而由公章也无法得到私章(现有技术下),因此用私章盖章,用公章验证私章的有效性,同时数公章中的总笔画数可验证和地址相符,这就完全保证了用私章盖章者是该地址的所有者,也就是签名的有效性

如果你接触比特币够久,你一定听说过比特币是个区块链,一个区块里包含很多交易,而交易都是链在一起的。那么,具体交易的细节如何?通常的技术文档都充满了术语,即使是中本聪的白皮书也难以直接联系实际,我最近又仔细研究了一下,这里用一种简单的比喻来解释下

比方说你的钱包里有三个地址A,B,C。你在地址A有1个币,你在钱包软件里把币发送到地址B,可以在区块链上查到这笔交易,不妨叫做交易甲。然后你又做了一笔交易乙,把币从地址B发到地址C。假设手续费是0.0001个币,每次发送你都花了0.0001个币作为手续费,那交易甲被确认后地址B就是0.9999个币,而交易乙被确认后地址C里就是0.9998个币

交易甲:地址A 1BTC -> 地址B 0.9999 BTC, 手续费 0.0001

交易乙:地址B 0.9999BTC -> 地址C 0.9998 BTC,手续费 0.0001

用账簿的比喻最好理解

账簿就是区块链,账簿的每页纸就是区块,这些纸依次装订在一起形成了一整个账簿。每页纸上贴满了一条又一条的汇款单(交易)

如果仔细观察汇款单交易乙(把0.9998个币从地址B转到地址C,并付0.0001手续费),你会发现交易乙是由两大部分组成,前一部分可称为付款信息(input),后一部分可称为收款信息(output)

按一般在银行填汇款单的习惯,付款信息里该填支出账户名(也就是地址B)和账户所有人签名(授权交易),而收款信息里应该填金额和收款方账户名(也就是地址C)。事实上,比特币交易也大致是这么写的,只有细微差别

交易甲

付款信息: 签名 公钥A (签名相当于盖章,是用地址A的私章(私钥)产生,而地址A的公钥可用于让其他人验证这个章是否有效 (私钥公钥加密原理到处都有))

收款信息: 0.9999 (金额) 地址B 兑现条件 (这里的兑现条件注明了未来要花地址B的币需要满足何种条件,下面有详述)

交易乙

付款信息: 签名 公钥B

收款信息: 0.9998 地址C 兑现条件

交易丙

付款信息: 签名 公钥C

收款信息: 0.9997 地址D 兑现条件

有几点和银行汇款单不同的地方

第一,每个汇款单都是花前一个汇款单的收款地址里的币,这样所有交易就一个个链结在一起,而如果要彻底核实某笔交易丙是否有效,就要顺着这个链一直回溯到最原始的挖矿产出交易(在交易甲之前还有别的交易),这样保证了只要用户有区块链的完整拷贝(也就是目前全节点的那60G数据),就可以独立验证任何一笔交易的有效性。

第二,每次汇款只能完全将支出账户里所有的币都花掉。以交易乙为例,汇款完成后原来的地址B就空了。如果只想转一半的资金到地址C,剩下的那一半就要在收款信息里另外填一个账户地址E,也就是所谓的找零地址

第三,总汇款金额小于地址B的部分就是手续费。如果地址B里有0.9999个币,汇款到地址C的金额是0.9998个币,那中间的差额0.0001就是矿工的手续费

第四,验证交易乙是否有效,是靠上一个交易即交易甲的收款信息中的兑现条件来保证的。可以有多种规则,目前最常见的两种就是提供收款地址的签名 (P2PKH)以及提供一段程序的哈希值(P2SH,这个涉及到哈希,一种防伪的手段)

如果你完全看懂了,那你对比特币交易的功能理解,就接近于core程序员的水平了,以后碰到很多名词如scriptSig (签名 公钥) 和scriptPubKey(兑现规则)之类你就很容易知道那都是汇款单上的哪个部分了

区块链驿站公众号
更多区块链信息请关注区块链驿站
郑重声明:本站主要用于区块链行业信息的传播,促进行业健康发展,部分信息均搜集转载自互联网 版权归原作者所有 如作者信息标记有误 请第一时间联系我们修改或删除 谢谢!

【编辑:考拉】