疑点之源
相信大家都看过上图。此图来自中本聪的比特币白皮书,用于介绍比特币交易。在这张图片的顶部,中本聪写道:我们将电子硬币定义为数字签名链。每个所有者通过数字签名前一个交易的哈希和下一个所有者的公钥并将这些添加到硬币的末尾,将硬币转移到下一个。收款人可以验证签名以验证所有权链。必须活着。
问题是,我明白他说的一切,但我还是不明白这张图片在说什么。也许比特币交易在中本聪的脑海里是这样的,所以我一直怀疑他是不是潜伏在地球上的外星人。脑回路和地球不一样,包括UTXO这个概念,真是和人类背道而驰。正常思维。因此,本文的任务就是尝试将这张图片转换成地球人容易理解的形式。
交易结构
如上图所示,这是一个比特币交易的简化结构(忽略了一些参数,简化了id)。
在介绍交易结构之前,先简单说一下比特币的UTXO概念,以方便零基础的读者。在比特币系统中,没有余额的概念,只有UTXO(Unspent Transaction Output),即未花费的交易输出。翻译成白话,我花的钱都是别人给我的钱,花的时候一定要花。例如,我有一个 2 BTC(比特币)的 UTXO。我想给你 1 BTC。我要花掉这个2 BTC的UTXO,然后生成两个UTXO,一个1 BTC的UTXO给你,一个UTXO(小于1 BTC),不同的是交易费)给我自己。看余额怎么办,查一下这个地址有多少个UTXO,把里面的BTC加起来就可以得到余额了。
好的,现在让我们看看交易的结构。比特币交易主要由输入和输出两部分组成。
输入是解释我打算花费的 UTXO 来自哪里。
具体参数包括:
txid:引用的UTXO所在的交易ID
vout:引用的UTXO所在的交易输出中的序列号(从0开始)
scriptSig:解锁脚本,包括本次交易的付款人签名()和付款人公钥(
).
输出是解释我计划生成多少个 UTXO,给谁,每个 UTXO 中有多少 BTC。
具体参数包括:
值:比特币数量
n:UTXO 序列号(从 0 开始)
scriptPubkey:锁定脚本,包括命令(OP_DUP等)和接收者的公钥哈希(
).
了解了交易的结构后,我们通过一个交易的例子来看看签名和验证是如何进行的。
交易签名
我们来看上图。 A通过交易001转给B 1BTC,B通过交易002转给C 1BTC。为简单起见,交易手续费问题忽略。
让我们重点分析交易 002。
B打算转1BTC给C,他先找到A转给自己的UTXO,即out of transaction 001中n=0的UTXO,将相关参数写入in transaction 002。然后在out中输入比特币数量和UTXO序列号来锁定脚本。锁定脚本中的命令是固定的,C 的公钥哈希(
) 可以通过解码C的钱包地址获得。
这样,交易002的相关数据就准备好了,最后的签名很短。这个签名类似于写支票时的签名,证明我同意给你钱。但是具体的实现比签信要复杂的多。原因是互联网上的一切都可以复制。如何证明你拥有这笔钱,如何证明交易是你自己创建的,没有被修改,是背后的原因。严格的数学理论和算法保证。
我们先来看看签名过程:
签名输入:
1.待签名的交易数据(输入和输出),即。
2.引用的相关UTXO信息(交易ID、序列号、锁定脚本)
3.B 的私钥,即
.
4. 签名类型
签名输出:
1.scriptSig,解锁脚本,包含签名()和B的公钥(
).
至此,一个完整的交易创建成功,可以发送到其他节点进行验证。
这里再说一句。细心的读者可能会发现,输入2的信息其实包含在输入1中,或者可以根据输入1找到,为什么要单独列出呢?目前还没有找到一个明确的、有说服力的解释,不知道还有没有其他深意。期待各位大神指教。
签名验证
交易发送到其他节点后,其他节点会对其进行验证,只有通过验证的交易才会继续传播。交易验证的项目很多,这里只讲签名验证。
签名验证有两个目的:
1.证明交易所报价的UTXO确实是付款方。
对于这笔交易,证明交易001序列号为0的UTXO确实发送给了B。
2.证明交易的所有数据确实是付款人提供的,没有被修改过。
具体到这个事务,证明B确实创建了事务002,并且事务中的数据没有被修改。
我们来看看验证是如何进行的。其实很简单。就是使用解锁脚本解锁UTXO对应的锁定脚本。上图对应的是橙色线连接的两个脚本:
OP_DUP OP_HASH160
OP_EQUALVERIFY OP_CHECKSIG
比特币脚本的执行基于堆栈模型,遵循从左到右,后进先出的原则。关于stack的介绍,文末参考文章中有清晰的说明,不清楚的读者可以参考。为了便于解释每个步骤的含义,本文采用文字进行描述。步骤如下:
1.入栈
2.
入栈
3.OP_DUP 复制栈顶的那个
,将副本放在栈顶。
4.OP_HASH160 到栈顶
复制 HASH160,
转换为
.
5.
入栈
6. OP_EQUALVERIFY 比较栈顶的两个元素是否相同,如果相同则移除这两个元素继续执行。如果它们不相同,将中断执行并返回失败。
7.OP_CHECKSIG 检查签名(注意栈中现有元素为
),根据结果返回成功或失败。
下面我们来分析一下每一步的含义。步骤1~6的意义其实很明显。使用 B 提供的公钥 (
) 双哈希(HASH160),然后用锁脚本中的公钥哈希(
) 为了比较,如果相同则返回成功。我们知道公钥哈希(
) 它是由 A 在创建交易时根据 B 的地址生成的。是B的公钥的双哈希计算,所以这一步只要提供了B的公钥,验证一定成功。因此比特币交易系统,步骤1到6相当于A向B的邮箱发送了1个BTC,B拿了钥匙打开邮箱,证明B确实拥有这1个BTC。即证明上面提到的验证目的1:证明交易001的序号为0的UTXO确实发送给了B。
比较麻烦的是第七步。这里的许多文章只是一般性或简要介绍。到这里学习的时候,真的就像掉进了迷雾里,茫然四顾。现在回想起来,文章中的一些说法是非常不准确的。这个简单的 CHECKSIG 操作实际上包含复杂的密码学和数学。它证明的不是所有权的问题,而是证明B确实创建了交易002并且交易中的数据没有被修改,也就是上面提到的验证目的2。
那么,CHECKSIG 的验证是如何工作的呢?这里使用椭圆曲线数字签名算法(ECDSA:The Elliptic Curve Digital Signature Algorithm),一种使用椭圆曲线进行数字签名和验证的算法。下面将简要介绍如何使用该算法对比特币交易进行签名和验证。涉及的数学不会深入介绍。感兴趣的读者可以参考文末的文章链接了解更多。
ECDSA
首先我们来看看椭圆曲线的形状,如上图红线所示。我们可以定义这条曲线上的点的加法:连接两点的直线与椭圆曲线关于X轴的交点的对称点是两点之和。如图,A+B=C。
对于A+A,我们取A点的切线与曲线关于X轴的交点的对称点。通过 A+A,我们可以轻松定义乘法。通过乘法,我们选择一个基点G,可以很容易地计算出K=kG。但是,给定K和G,很难计算k(目前还没有有效的算法)。这就是椭圆曲线离散对数问题。 ECC Elliptic Curves Cryptography 的安全性是基于椭圆曲线离散对数问题的难度。基于此,在ECC中我们定义k为私钥,K为公钥。
接下来我们看基于有限域Fp的椭圆曲线域E(Fp):
y^2 ≡ x^3 + ax + b (mod p)
当:a, b ∈ Fp 且 4a^3+27b^2 ≠ 0 (mod p)., x, y ∈ Fp, 这条曲线上的点集 P=(x,y) 是基于有限域Fp的椭圆曲线域E(Fp)。
要完整描述一个椭圆曲线域实际上需要 6 个参数:
p:定义有限域边界的素数
a、b:椭圆曲线参数
G:基点
n:G的阶数,nG=O∞
h:残差因子,控制点的密度。
椭圆曲线场可以简单理解为只取椭圆曲线上的那些整数点,但是因为额外的模运算,显示的形状与之前的平滑曲线不同(如下图所示),但是之前定义的加法和乘法规则不变。
好的,有了这些概念,现在让我们看看签名和验证过程:
签名者的密钥对:(d, Q); (d 是私钥,Q 是公钥)
需要签名的信息:M;
签名:签名(M) = (r, s)
签约流程:
1、根据ECC算法随机生成一个密钥对(k, R),R=(xR, yR)
2、令r = xR mod n,如果r = 0,返回步骤1
3、计算 H = Hash(M)
4、根据数据类型转换规则,将H转换成大端整数e
5、s = k^-1 (e + rd) mod n,如果s = 0,返回步骤1
6、 输出的 S = (r,s) 是签名。
验证过程:
1、 计算 H = Hash(M)
2、根据数据类型转换规则,将H转换成大端整数e
3、计算 u1 = es^-1 mod n,u2 = rs^-1 mod n
4、Calculate R = (xR, yR) = u1G + u2Q,如果R = 0比特币交易系统,验证签名无效
5、令 v = xR mod n
6、如果v == r,则签名有效,如果v≠r,则签名无效。
从数学上可以证明,如果 v == r,则可以证明信息 M 确实是由持有密钥对 (d, Q) 的签名者签名的,并且没有被修改。
上述过程中的Q、S、R都是椭圆曲线域内的点。
我们来对比一下上面例子中的输入参数和比特币交易002中的参数:
如上图所示,可以看出两个进程中的参数是一一对应的。我们将根据示例对交易002中的相关参数进行相应的操作,不难理解签名验证的具体过程。 由于数学原理的保证,如果签名验证成功,可以证明B确实创建了交易002,并且交易中的数据没有被修改,这就是上面提到的验证目的2。
好的,以上就是作者目前对比特币交易中签名和验证的理解和思考。水平有限,难免有错误和遗漏。欢迎大家批评指正!
ECDSA 部分的两个动画引用自参考文章。我要向原作者 Nick Sullivan 以及所有参考文章的作者表示感谢!
参考文章
[1]深入比特币原理(四)——锁定脚本和解锁脚本)
[2] 比特币交易数据结构和签名类型
[3] 椭圆曲线密码学简介
[4] 比特币系统采用的公钥密码体制和ECDSA签名算法介绍-第1部分:原理