主页 > imtoken钱包app下载 > [比特币] 公钥和私钥、地址、数字签名和交易

[比特币] 公钥和私钥、地址、数字签名和交易

imtoken钱包app下载 2023-06-01 05:54:01

比特币交易中的签名和验证

最近在学习一些比特币相关的原理和实现机制。学习过程中难免会出现一些问题。有些问题可以得到满意的回答,并且有一种清晰的感觉。但是,也有一些问题我一遍又一遍地想不通。看了很多文章,我还是有一种模糊的感觉,就像陷入了迷雾。比如比特币交易中的签名和验证,这个签名和哪个交易有关?签名的内容是什么?验证如何验证?验证证明了什么?以上问题花了我很长时间收集数据,比较和思考。至此,我想我已经有了比较完整的认识和了解。虽然不能保证完全正确,但还是打算总结一下。

疑惑的来源

相信大家都看过上图,这张图来自中本聪的比特币白皮书,介绍了比特币交易。在这张图片的顶部,中本聪写下了以下文字:我们将电子硬币定义为数字签名链。每个所有者通过对先前交易的哈希和下一个所有者的公钥进行数字签名并将它们添加到硬币的末尾来将硬币转移到下一个所有者。收款人可以验证签名以验证所有权链。为了保持原汁原味,我就不翻译了。相信大家的阅读理解能力还是保留下来的。直播。

但问题是,我明白他说的一切,但我还是不明白图片在说什么。可能比特币交易在中本聪的心目中是这样的,所以我一直怀疑他是不是潜伏在地球的外星人,他的脑回路和地球的脑回路不一样,包括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,即001交易中n=0的UTXO,将相关参数写入002交易的in中,然后输入出入比特币数量,UTXO序列号,并锁定脚本。锁脚本中的命令都是固定的,C的公钥哈希(

) 可以通过解码C的钱包地址得到。

这样,002交易相关的数据就已经准备好了,还需要最后的签名。这个签名类似于写支票时的签名,证明我同意给你钱。但具体的实现比签信要复杂得多。原因是互联网上的一切都可以复制。如何证明你拥有这笔钱,如何证明交易是你创建的并且没有被修改过,有严谨的数学理论和算法保证。

我们先来看看签名过程:

签名输入:

1.要签名的交易数据(输入输出),即。

2. 引用的UTXO相关信息(交易ID、序列号、锁脚本)

3.B的私钥,也就是

.

4. 签名类型

签名输出:

1. scriptSig,解锁脚本,包含signature()和B的公钥(

比特币公钥如何查询

)。

至此,一个完整的交易创建成功,可以发送到其他节点进行验证。

这里再说一句。细心的读者可能会发现,输入2的信息其实包含在输入1中,或者可以根据输入1找到,那为什么要单独列出呢?目前我还没有找到明确的、令人信服的解释,也不知道还有没有其他深意。期待大神们的指导。

签名验证

交易发送到其他节点后,其他节点会对其进行验证,只有经过验证的交易才会继续传播。交易验证的项目很多,这里只讲签名验证。

签名验证的目的是双重的:

1.证明交易所引用的UTXO确实属于付款人。

具体到这个交易,是为了证明交易001中序号为0的UTXO确实是发给B的。

2.证明交易的所有数据确实是付款人提供的,没有被修改过。

具体到这个事务,就是证明B确实创建了事务002,并且事务中的数据没有被修改过。

让我们看看验证是如何执行的。其实很简单。就是使用unlock脚本来解锁UTXO对应的lock script。上图对应橙色线连接的两个脚本:

OP_DUP OP_HASH160

OP_EQUALVERIFY OP_CHECKSIG

比特币脚本的执行基于栈模型,遵循从左到右、后进先出的原则。关于栈的介绍,文末的参考文章中有比较清晰的图解,不清楚的读者可以参考。在本文中,为了方便解释每个步骤的含义,都用文字来描述。每个步骤的操作如下:

1.入栈

2.

入栈

3. OP_DUP 复制栈顶

,将副本放在栈顶。

4. OP_HASH160 HASH160 栈顶的副本

比特币公钥如何查询

,

转换为

.

5.

推入堆栈

6. OP_EQUALVERIFY 比较栈顶的两个元素是否相同,如果相同则移除这两个元素,继续执行。如果不同,则会中断执行并返回失败。

7.OP_CHECKSIG 检查签名(注意堆栈中的现有元素是

),并根据结果返回成功或失败。

我们来分析一下每一步的含义。步骤1~6的意义其实很明显。使用公钥(

B提供的

)进行双重哈希(HASH160),然后与公钥哈希(

) 在 lock 脚本中,如果相同,则返回成功。我们知道公钥哈希(

) 是A在创建交易时根据B的地址生成的,是通过B的公钥的双哈希运算得到的,所以只要在这个提供了B的公钥步骤,验证必须成功。因此,步骤 1 到 6 相当于 A 向 B 的邮箱发送了 1 个 BTC,B 用钥匙打开了邮箱,证明 B 确实拥有 1 个 BTC。也就是证明上面提到的验证目的1:证明交易001中序号为0的UTXO确实是发给B的。

比较麻烦的步骤是第7步。很多文章在这里只是笼统地谈,或者简单提一下。当我了解到这一点时,就像陷入迷雾中,环顾四周,我不知所措。现在回过头来看一些文章里的说法,很不准确。这一步简单的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椭圆曲线密码学的安全性是基于椭圆曲线离散对数问题的难度。基于此,在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:辅因子,控制点的密度。

椭圆曲线域可以简单理解为只取椭圆曲线上的那些整数点,但由于多了一次模运算,显示的形状与之前的平滑曲线不同(如下图所示),但是前面定义的加法和乘法规则没有改变。

好的,有了这些概念,现在让我们看看签名和验证过程:

签名者的密钥 Right: (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、计算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部分:原理