有关Bitcoin中部分签名的提取
前言
刚刚接触Bitcoin Wallet 里面的构造还不是很清楚,提取和解析指令也不是很熟悉,所以听到这个题目,有些无从下手,于是我先熟悉了bitcoin-cli的指令,例如:getblockhash + 区块高度、getblock + blockhash、getrawtransaction + Tx、decoderawtransaction + (getrawtransaction所获得的字符串),想要获得签名r主要是通过这些指令,之后我学习了解析交易字符串后的各部分所代表的含义,通过学习精通比特币,我了解到在交易过程中,存在解锁脚本和锁定脚本,结合解析出的信息,我发现里面存在scriptSig这个字段名,但是里面存在两个字段:asm和hex,深入了解后发现,hex代表的是签名脚本的16进制字符串,至此我找到了目标提取字符串。下面具体介绍提取过程。
实验目的
提取出比特币钱包所有签名字段中的r,并找到相同的签名r。
预备知识
UTXO
比特币交易的基本单位是未经使用的一个交易输出UTXO。它是不可再分割的,在比它的金额还小的交易中就会存在找零行为,即会产生多个输出。实际上,并不存在存储比特币账户金额的地点,只有被所有者锁住的、分散在比特币网络中的UTXO。
锁定脚本
放在交易输出上的一个障碍,给出了花费UTXO的条件,一般包含条件操作符和限定公钥。
解锁脚本
是一个满足是锁定脚本限定条件的脚本,从而允许锁定的UTXO被花费,它也是交易输出的一部分,一般包含数字签名和对应公钥。
比特币交易的具体过程
当userB给userC发送btc时,会新产生UTXO,观察图中的橙色连线,我们发现,新产生的UTXO中的in中scriptSig的公钥与之前的UTXO中scriptPubKey的公钥相同,其实在交易的过程中,解锁脚本需要满足未花费UTXO锁定脚本的条件,通过脚本语言验证,也就是之前交易的输出,证明是其拥有者,即可将其中的比特币调出,生成新的交易输出。所以交易过程中签名就存放在解锁脚本里面,后面通过解析交易字符串,我们就可以明确的找到scriptSig的所在了。
ECDSA
在比特币系统中,所采用的是椭圆曲线数字签名算法来对交易进行签名。签名会产生两部分:r、s
解析交易字符串及部分字段的含义
vin:交易输入数组
txid:交易ID
vout:交易输出序号
scriptSig:签名脚本
asm:签名脚本的汇编码
hex:签名脚本的16进制字符串表示
sequence:输入序列号
发现scriptSig中存在两个字段asm和hex,签名r到底在哪个字段里面呢?
Transaction字符串的详解含义图
ScriptSig
Lr的含义是签名r的长度,且每个小长方形代表两个字符,所以我们可以通过计算得到签名r的长度,从而可从字符串中截取出来。
举个实例看一下:
hex
483045022100d71db39ae4f6bc3128d78661f6951bb17b097ab32e1ead3ce6fe761914715dd502201970b34d36a9fef053b8b7a3c4555ef5bba14a88992449b980aee862465d966e01410404ac8c30c4e85f47702bfa8d8d56d8e614258958d6655611474da6cadb8c73195dc7951db3466caabd256ebc9f6ef87fcdb597b6cb048dd1bbf011713690ba19
其中黑体部分就是签名字段中的R
Lr=οχ21⟹32byte⇒32×8=256bit⇒256÷4=64
所以可以得出签名r的长度是64,即在21之后的64个字符为签名r
至此,我们找到了需要提取的内容,我们可以通过编写脚本语言将其导出,但是截止2020年1月10日,整个比特币钱包的大小为300G,所拥有的的区块数目是612345,数据量较大,不容易导出。
实验过程
主要任务就是将数据导出,刚开始没有一点思路,慢慢地发现可以通过编写python代码,将数据导入到指定文件中去,一开始我是直接在服务器上写代码,将hex导出到文件中去,但是不知道如何将文件放到本地,并且通过指令操作文件、运行代码比较麻烦,就找到了另外一种方法,pycharm可以连接到服务器,可以对服务器上代码以及文件直接操作即可,但是比特币网络中的数据量太大,想要导出签名所需要耗费的时间太多,目前我只导出了前610000个区块的tx,后续导出签名的代码出现问题,还在修改中,希望能尽快导出所有的签名R。