请选择 进入手机版 | 继续访问电脑版
 找回密码
 立即注册
  • QQ空间
  • 回复
  • 收藏

谁控制了比特币,是你?还是钱包?| 比特币地址与交易原理深析

admin| 2018-9-29 09:42 阅读 191 评论 0

1

如果你在使用比特币钱包,却无法回答上述3个问题,那么这篇文章专为你定制。

比特币被锁死在无效地址

近日,安比(SECBIT)实验室在审计数字钱包源码时,发现一个名为 pywallet 的比特币钱包开源库内含一个严重缺陷:如果向 pywallet 生成的 OmniLayer 收款地址转账,将导致资产永久丢失。

据安比实验室区块链技术专家 zer0to0ne 解释,OmniLayer 协议允许在比特币区块链上发行自定义资产(比如 USDT)。OmniLayer 资产交易的本质是比特币交易。

比特币交易的代码库有很多,pywallet 便是其中一种。它能方便地构造符合 OmniLayer 格式的比特币交易。目前 pywallet 已经被应用在一些数字钱包软件中。

但开源库 pywallet 在生成 OmniLayer 钱包地址的时候,误将地址的前缀写反了,致使若干比特币资产被锁死在无效的地址内。

2

图1为 pywallet 相关错误代码截图

小葱注:比特币网络上最常见的地址类型有三种:普通公钥地址(1-地址),脚本哈希地址(3-地址)和隔离见证地址(bc1-地址),地址类型通过地址的前缀来区分。其中1-地址的前缀为 0×00,3-地址 的前缀为 0×05。三类地址用途各异。

3

前述的开源库 pywallet 颠倒了地址前缀,将1-地址错误地设置为3-地址。因此原本要转给1-地址的资产会误转入3-地址。

当用户以1-地址的验证方式(即私钥签名)去取出资产时,区块链网络却以3-地址执行脚本的方式来执行验证,从而导致用户无法正常取出资产。

安全专家:比特币从未真正实现过转账功能

众所周知,比特币的实现是基于 UTXO 模型,这与我们直观理解的账户模型有很大区别。

安比实验室区块链专家zer0to0ne告诉小葱,实际上比特币从未真正实现过通常意义上的转账功能。中本聪只给比特币设计了一系列比特币脚本操作符和比特币脚本执行器,而所谓的转账过程,实际是由一段比特币脚本锁定、解锁过程来模拟。这与日常生活中的账本概念(或称账户模型)是不一样的。

为便于理解,我们可以把比特币区块链上的资产交易比喻成将资产锁进保险箱,只有持有保险箱钥匙的人(即收款人)才能拿出保险箱中的资产进行交易。

4

来源:比特币白皮书https://bitcoin.org/bitcoin.pdf

举个栗子:

【如果 Alice 要向 Bob 支付一笔资产,Alice 需将这笔资产锁进一个保险箱中,只有 Bob 才有这个保险箱的钥匙,即只有Bob才能取出这笔资产。如果 Bob 想取出资产,他必须同时花掉这笔资产(即锁入另一个保险箱)。在 Bob 未取出资产前,资产并不真正属于 Bob】【试想若 Bob 丢了钥匙,他将无法再取出资产。 换句话说,当这笔资产存于保险箱时,它既不属于Alice,也不完全属于Bob。当然,Alice 也可以把资产放入任何人都可以打开的保险箱中,这也被称之为 Anyone-Can-Spend 交易】

付款人为收款人定制一个保险箱,将资产放入保险箱中并上锁,再将保险箱丢到公共场所,收款人自行前往解锁。由于比特币区块链上的收款地址类型不同,相应的保险箱类型、开启保险箱的钥匙,以及保险箱的解锁过程也有区别。

5

为什么说比特币从未实现真正意义上的转账功能?

因为比特币系统中根本就不存在账户概念,账户之间的转账也无从谈起。一个人能在未来打开多少个保险箱,也还是未知数。

基于上述解释,我们很容易理解:当 pywallet 开源库误将1-地址识别为3-地址时,就好像将原本的1-类保险箱改造成了3-类保险箱,而账户持有者还是拿着1-类保险箱的钥匙去解锁,能打开才怪。

被误锁的资产还有救吗?能否采用1-地址的钥匙去开启3-保险箱?

那么此前提及的被误锁住的 OmniLayer 数字资产究竟能不能找回呢?

安比实验室zer0to0ne 表示,小白可能首先需要弄懂两个重要概念 P2PKH(Pay to Public Key Hash) 与 P2SH (Pay to Script Hash)才能理解答案。这两个名词分别代表地是两种不同比特币交易类型。

P2PKH:中本聪的伟大发明

P2PKH(Pay to Public Key Hash),即将比特币放入一个保险箱,钥匙孔为公钥 Hash(Public Key Hash)。我们最常见到的1地址本质上就是 Public Key Hash 的一种编码。1-地址的生成过程很简单,将公钥经过Hash160运算得到 Public Key Hash,在 Public Key Hash 头部补上前缀 0×00,尾部补上校验和,经过Base58便得到了1开头的比特币地址。

6

再看看P2PKH交易类型的保险箱构造过程,以Alice发送比特币给Bob为例。付款方 Alice 在构造保险箱的时候需设置一个锁定脚本:

7

注:可把这一步理解为 Alice 为 Bob 定制了一个保险箱,把比特币放入保险箱并用 Bob 的公钥 PubKey Hash上锁。现在这把锁除了持有私钥的 Bob,谁都无法打开。

当 Bob 要花费 Alice 给他的比特币时,需提供必要的参数:交易签名 + 公钥(技术黑话:scriptSig)来开启保险箱,使得锁定脚本执行后返回 True,这一步通常由钱包自动完成。

那么比特币节点是如何校验 scriptSig 合法性的?

8

图片来自Mastering Bitcoin

脚本执行过程上图所示,Bob将交易签名后得到的数据(实际上还要包含数据长度信息),真正的scriptSig 应该为<sig len> <sig> <pubKey len> <pubKey>,比特币脚本执行器从 PUSH 数据开始,PUSH 操作会读取第一个字节获取将要入栈的数据长度信息,然后持续执行比特币脚本,直到最后执行完毕检查执行结果。

【首先入栈的是 <sig>,然后将 <PubK> 入栈,一次DUP操作将在栈顶复制一份 <PubK>,HASH160弹出栈顶的 并计算Hash,将结果压回栈中,之后使用 EQUALVERIFY 弹出Hash对比是否合相等,如果相等则返回True,不相等便标记交易为无效。执行到这一步,暴露了公钥,确保了签名者的身份的正确性,但是黑客或矿工可以通过暴露的公钥构造出一个新的交易替换原始交易,无法保证安全,那么便需要下一步来保证交易无法伪造。此时栈上还有 <PubK> 和 <sig>,执行 CHECKSIG,将校验数字签名的正确性,确保了签名者拥有地址对应的私钥。】

数字签名除了持有私钥的人,谁也无法伪造。执行至此,一笔比特币P2PKH交易已经安全地完成了。

此时,细心的读者可能会注意一个细节:如果 Bob 取出钥匙,在他还未打开保险箱时,区块链上的任何矿工都能看得见这把钥匙的形状,理论上他们能立即复制一把钥匙,把 Alice 留给 Bob 的保险箱打开并花掉(俗称 Front-running 攻击)。

显然中本聪考虑了这个问题,这把钥匙中的交易签名是 Bob 发起的交易的完整签名。假设 Bob 要将 Alice 构造的保险箱中的比特币 装入一个新的保险箱(留给Charlie),这时Bob 出示的钥匙包含了 Charlie 的公钥Hash,矿工虽然可以复制 Bob 的钥匙,但是这把钥匙已经隐藏了下一个新保险箱的关键信息,因此矿工无法使用这个复制钥匙来完成别的动作(无法挪用数字签名)。

P2SH:后中本聪时代的重大创新

中本聪设计了一个这么强大的脚本系统,只用来构造转账交易似乎太浪费,因此有开发者尝试用其他指令构造一些特别的锁定脚本,并使用其他方式来解锁。

例如构造一个用 Hash 原象(Pre-image)来解锁交易的脚本:

9

该脚本含义是:当满足 Hash160(Pre-image)==<Hash>这一条件时,便可成功将脚本解锁。该脚本有两个神奇的功能:

  • 交易构造的输出足够短,意味着比特币节点维护的 UTXO 缓存占用空间会大大减小;
  • Pre-image 总是在交易被花费时作为 input 来引用,不会在交易的 output 侧出现,UTXO依然保持精简,同时可以把手续费负担转嫁给接收方。

但是,这个脚本存在很大安全性问题。继续从保险箱的例子来理解,并给这类保险箱起名3-类保险箱。

【Alice 给 Bob 的比特币锁定在一个由上述 Hash160保护的保险箱里,我们姑且称之为哈希锁吧。这把锁依然需要正确的形状才能开启,但安全性弱很多。由于缺少数字签名机制导致钥匙隐藏的关键信息不会随着Bob 新建的保险箱而变化。任何矿工都能在 Bob 亮出钥匙的一瞬间复制出一摸一样的钥匙,抢着去开Alice留给Bob的保险箱(Front-running),将币转给另一个人 (Eve)。】

不慌。比特币核心开发者 Gavin Adresen 提出的P2SH(Pay to Script Hash )技术,正是为了让上述交易方式更安全。

P2SH 的交易输出依然是校验 Hash160(Script)==<Script Hash>,但在校验完毕后又增加了一个步骤:使用比特币脚本执行器再次运行 Script 本身。

这样事情就变得有趣了,在前 P2SH 时代 Script 仅仅作为 Hash160 的原象存在,而激活了P2SH后,Script 必须要求是一段有意义、可执行的比特币脚本。我们可以在 Script 中加入数字签名检查的指令,或者多重签名检查功能,甚至智能合约都可以在P2SH的基础上进行开发,既使用了强大的比特币脚本,又能让交易保持精简。并且由于 P2SH 交易地址中只存有 Script Hash,在交易被成功花费之前,任何人都无法知晓 Script 内容,很好地保护了隐私。

P2SH在2012年4月1日激活,开启了比特币的P2SH时代。

比特币开发者为这类交易创建了特殊的地址,用3开头。现在全世界的3-类保险箱经过升级,再也不怕钥匙被复制,因为保险箱的钥匙会内置芯片。升级后的保险箱除了能够校验钥匙形状,更能读取钥匙中内置的芯片的数据,芯片中的内容会影响钥匙的形状。

【Bob制作了一个能够校验钥匙芯片中数字签名的保险箱,让Alice把钱放进这个保险箱然后锁起来。Bob开启保险箱的钥匙形状虽然可以被复制,但这把钥匙内置了芯片,芯片能包含各种高级约束条件,保证钥匙不被越权滥用。保险箱会在校验完形状后,执行钥匙芯片内的程序检查有效性,两项检查都通过才能开启保险箱。】

被锁死的币是否还能挽回?NO!

再回到之前的问题,能否采用1-地址的钥匙去开启3-类保险箱 ,挽回被锁住的资产呢?

这个问题可理解为:Alice 按照 Bob 的要求制作了一个3-类保险箱(其实它是被 pywallet 错误修改成了3-类保险箱),Bob 本意是要一个1-类保险箱 ,因为他手里只有一个1-类保险箱的钥匙。当Alice以3-类保险箱把比特币转给Bob时,这个保险箱需要同时校验钥匙形状+钥匙芯片内容了,但Bob的1-类保险箱钥匙形状是Public Key决定的,在误变为3-类保险箱后,钥匙形状校验没变,但他没有相应的钥匙芯片内容。

Bob 尝试在钥匙芯片中写入Public Key,使得钥匙形状和锁匹配,但芯片中的Public Key 却无法被保险箱正确执行,所以 Bob 可能再也无法将他的比特币从保险箱中解锁了。

SegWit(隔离见证):全新时代来临

比特币开核心发者 Eric Lombrozo, Johnson Lau, Pieter Wuille 提出了一种全新的概念——隔离见证(Segregated Witness,简称SegWit)。这是一种有效缓解比特币区块拥堵的技术,并彻底解决了交易延展性问题(Transaction Malleability)。

在SegWit升级前,每一个用完的钥匙都插在保险箱上,钥匙占据了一定的体积导致仓库无法密集堆积这些用完的保险箱,总是要为了露在外面一大截的钥匙腾空间。于是,比特币开发者们开始思考如何把钥匙体积减小,并且用足够廉价的材料来制作钥匙,节约成本。

SegWit(隔离见证)应运而生。它干脆直接把锁从保险箱上移走,变成一个远程无线校验的保险箱,用户可以把钥匙统一插在远离保险箱的地方来远程开启对应的保险箱。

2017年08月24日,SegWit软分叉被正式激活,结束了旷日持久的矿工开发者对峙。

为了兼容3-类保险箱,比特币开发者使用了一种叫做P2SH-P2WPKH的技术,即通过P2SH来包裹P2WPKH交易,让P2WPKH交易能骗过不支持SegWit的老旧节点。还有一种类似P2SH包裹的P2WSH技术(P2SH-P2WSH),此处不多介绍。

首先解释一下P2WPKH是什么:

【P2WPKH全称Pay to Witness Public Key Hash,相较于P2PKH,P2WPKH把scriptSig移到交易外部,节省了占用的区块空间】

为了向前兼容未及时升级的比特币节点,这个P2SH是这样构造的。Bob首先产生一个P2PKH地址,从地址中解析出PubKey Hash,然后构造一个脚本:

10

然后计算Script的Hash160得到Script Hash,构造出一个3地址:

11

当 Alice 把币锁定到 Bob 提供的 <Script Hash> 中,意味着 Bob 要提供正确的 Script 才能解锁。Bob通过构造有效的Script通过了钥匙形状检查,并且钥匙里的程序也能被保险箱正确解析并执行。细心的读者应该又发现了问题,这个钥匙却少了相关安全性约束,很容易被复制,(Front-running)矿工有机会将交易篡改,把币转给其他人。

但无需担心,升级了 SegWit 之后,支持 SegWit 的比特币节点会在校验 P2SH 后再额外地校验Bob的签名是否正确,数字签名作为独立于交易之外的安全约束,不再占用宝贵的区块空间。

谈及SegWit,zer0to0ne表示:

「SegWit 为比特币扩容做出了贡献的同时,也同时在保持向前兼容性上面付出了一些代价。在原生 SegWit 交易被广泛采用之前,使用了混乱的 P2SH 兼容技术。如果未来比特币全部统一到 bc1-地址 ,就可以彻底避免使用P2SH 包裹技术,并且最大限度地利用区块容量。」

了解了这么多干货后,我们再回到文章开头的三个问题,答案一目了然。

121314

文章点评