比特币系统会让新人困惑的原因之一是背后的技术重塑了“拥有者”的概念。
传统上,“拥有”某物——,如不动产或货币——,是指要么由个人保管,要么委托给一个可信赖的实体(如银行)。
比特币系统的情况就不一样了。比特币本身既不是集中存储,也不是本地存储,所以没有实体是它的托管人。
比特币作为记录存储在一个名为“区块链”的账本中,账本的副本在一个由互联电脑组成的志愿者网络中共享。
“拥有”比特币只意味着有能力将控制权转移给他人。——是通过在区块链中创建转移记录来实现的。但是这种能力怎么保证呢?通过ECDSA私钥和公钥对。这是什么意思?如何保证比特币系统的安全性?
让我们揭开盖子,看看下面是什么。
ECDSA是椭圆曲线数字签名算法的缩写。它是使用椭圆曲线和有限域对数据进行“签名”的过程。这样,虽然第三方可以验证签名的真实性,但签名人仍然可以保留创建签名的专有能力。在比特币系统中,“已签名”的数据是指所有权转移时的交易。ECDSA将签名过程与验证过程分开。每个过程都是由几个算术运算组成的算法。签名算法使用私钥,验证算法使用公钥。我们稍后将演示一个示例。
但首先,为椭圆曲线和有限域的速成课程铺平道路。
椭圆曲线椭圆曲线的代数表达式是以下方程:
y2=x3 ax b
其中a=0,b=7(比特币系统使用的版本),其图形如下:
椭圆曲线有一些有用的特征。例如,非垂直直线与椭圆曲线相交于两点。如果这两个点不是切点,那么曲线上一定有第三个点与那条直线相交。另一个特点是曲线上任意一点的非垂直切线必须且只能与曲线有另一个交点。
利用这些特性,我们可以定义两种运算:“异点相加”和“同点加倍”。(译者注:加法运算是由和弦规则定义的)
“异点相加”,P Q=R,定义为:R是基于X轴的R '反射点(对称点)。其中R’是包含p和q的直线与曲线的第三个交点。用图形方式最容易理解:
同样,“同一点加倍”,P P=R,定义为:作一条过P点的切线,先找出切线与曲线的另一个交点R’,然后基于X轴计算反射点R’。
结合这两种运算可以用于标量乘法,R=a P,定义为将点P加到自身a倍。例如:
R=7P
r=P(P(P(P(P(P(P P)))))
标量乘法的运算过程可以用“异点相加”和“同点加倍”相结合的方法来简化。例如:
R=7P
R=P 6P
R=P 2 (3P)
r=P ^ 2(P 2P)
这里,7P被分解为“同一点加倍”和“不同点相加”两个步骤。
有限域ECDSA中的有限域可以理解为一个预定义的正区间,所以每次运算的结果都必须包含在这个区间内。任何在区间之外的数字都应该“换行”以使其落在区间之内。
实现这个目标最简单的方法就是求余数,即通过模运算(mod)来实现。例如,9/7的结果是1和2的商:
9 mod 7=2
这里我们的有限域是模7,在这个有限域上的所有模运算都会得到一个落在0到6范围内的结果。
ECDSA使用的椭圆曲线是基于有限域的,它极大地改变了曲线的外观,而不是改变曲线所基于的方程或特殊性质。使用与上图相同的等式,在模数为67的有限域中绘制后看起来是这样的:
现在变成了一组点,所有的x值和y值都是0到66之间的整数。注意,这条“曲线”在水平方向保持对称。
“加异点”和“同点翻倍”在视野上略有不同。地图上画的直线要像“小行星”游戏中一样,在水平和垂直方向包裹,保持相同的斜率。因此,( 2,22)和(6,25)“差异的增加”的图形如下:
第三个交点是(47,39),它的反射点是(47,28)。(译者注:28=6739)
回到ECDSA和比特币,比特币等协议为椭圆曲线及其有限域选择一组参数,协议下所有用户使用的参数是固定的。这组参数包括所使用的方程、有限域的素数模以及曲线的“基点”(G)上的一个点。基点的“阶”(n)不是单独选取的,而是与其他参数形成一个函数,可以形象地想象为“基点”反复加到自身上直到切线的斜率为无穷大(或变成多条直线)的次数。(译者注:“顺序”的算术表示是nG=O中的n)
比特币系统设置了一些非常大的数作为“基点”、质数模和“阶”。事实上,ECDSA在所有实际应用中都使用非常大的值。基于这些值的算法非常安全,试图暴力破解或逆向工程是不现实的。
在比特币系统中:
椭圆曲线方程:y2=x3 7
质数模数=225623229282726241=fffffffffffffffff c2f
基点=04 79 be 667 e 9 f 9 DCB BAC 55a 06295 ce 870 b 07 029 BF CDB 2d ce 9 59f 2815 b 16f 81798 483 ad 77 263c 465 da 4 fbfc 0e 108 A8 FD 17b 448 a 6855419 c47d 08f FB 10 D4 b 8。
order=fffffffffffffffffffffe baa edce 6 af 48 a 03 b bfd 25 e 8 CD 0364141
谁选择了这些数字,为什么?围绕合适参数的选择,产生了大量的研究,也抛出了相当数量的阴谋论。毕竟一个巨大的,看似随机的数字,可能隐藏着重构私钥的后门。简而言之,这个具体的实现被命名为secp256k1,它是密码学中使用的基于有限域椭圆曲线的求解系统中的一员。
私钥和公钥把这些规则放在一边,现在是时候了解私钥、公钥以及它们之间的关系了。简单总结一下:在ECDSA中,私钥是用不可预知的方法选择的一个介于1和“顺序”之间的数。公钥是由私钥计算的,它是通过“基点”和一个等于私钥的值的标量乘法计算的。计算公式为:
公钥=私钥基点
这说明私钥的最大可取值(也是比特币地址数)等于“阶”。
在一个连续的域上,我们可以画一条切线,在地图上标记公钥,但是有公式可以在有限域上做同样的工作。p q“不同点相加”求构件中R的计算公式如下:
c=(QYpy)/(qxpx)
rx=C2pxqxry=c(pxrx)py
p“同一点加倍”求r的公式如下:
c=(3px2 a)/2py
rx=C22 pxry=c(pxrx)py
在实际计算中,公钥的计算被分解为从“基点”开始的“同点加倍”和“不同点相加”的一系列运算。
下面以一个小数字为例,演示一下底层的操作过程,从而直观地了解密钥是如何构造的,如何用于签名和验证。我们使用的参数是:
等式:y2=x3 ^ 7(即a=0,b=7)。
质数模数:67
基点:(2,22)
订单:79
私钥:2
首先,找到公钥。因为我们选择值为2的最简单的私钥,所以只需要将基点加倍一次。计算过程如下:
c=(3 * 22 0)/(2 * 22) mod 67
c=(3 * 4)/(44)模67c=12/44模67
这里我们要先停下来做几个小技巧:当结果必须总是整数时,如何在有限域上做除法?我们必须用倒数来做乘法,但这里篇幅不够,无法解释(有兴趣可以参考这里和这里)。此时此刻,请先相信我们的计算:
44-1=32
让我们继续:
c=12 * 32 mod 67
c=384 mod 67c=49
rx=(4922 * 2)mod 67rx=(24014)mod 67rx=2397 mod 67rx=52
ry=(49 *(252)-22)mod 67ry=(49 *(50)-22)mod 67ry=(-245022)mod 67ry=-2472 mod 67ry=7
所以我们公钥对应的点是(52,7)。这些是值为2的私钥所需的操作!
与试图从公钥推导出私钥相比,从私钥到公钥更容易计算。在椭圆曲线加密的实际应用中,可以从公钥推导出私钥,但在计算上不可行。
因此,从私钥获取公钥是一种单向的设计。
与私钥一样,公钥通常由一串十六进制数字表示。但是等等,我们怎么把平面上两个数字代表的点变成数字呢?在未压缩格式的公钥中,代表X和Y坐标的两个256位数字粘合在一起,生成一个长字符串。我们还可以利用椭圆曲线的对称性,生成一个压缩格式的公钥,只保留x值来表示点位于曲线的哪一侧。从这部分数据,我们可以还原两个轴的坐标。
用私钥签名现在我们有了一对私钥和公钥,对一些数据进行签名吧!
数据可以是任意长度。通常,第一步是对数据进行哈希运算,生成一个与曲线的“等级”数(256)相同的数。这里为了使文章简洁,我们省略了hash步骤,只对原始数据z进行签名,我们用G表示“基点”,N表示“顺序”,D表示私钥。签名方法如下:
1.在1和n-1之间选择一个整数k;
2.用标量乘法计算点(x,y)=kg;
3.设r=x mod n,如果r=0,返回步骤1;
4.设s=(z r d)/k mod n,如果s=0,返回步骤1;
5.(r,s)是签名。
需要提醒的是,在第四步中,如果计算结果中有分数(实际计算中总会出现这个分数),就要用分子乘以分母的倒数。第一步,在做不同的签名时,一定要注意使用的k值不能重复,不能被第三方猜到。换句话说,k的值要么是一个随机数,要么是一种确定性的方法,使第三方无法窃取机密。否则,将从步骤4中提取私钥,因为s、z、r、k和N都是已知的。您可以在这里了解过去出现过的这种类型的漏洞。
我们选择数字17作为待签名的数据,按照下面的方法计算。这些变量如下:
Z=17(数据)
N=79(顺序)G=(2,22)(基点)d=2(私钥)
1.选择一个随机数:
k=兰特(1,n1)
k=兰特(1,791)
K=3(“这真的是随机的吗?我读书不多,别骗我!”“嗯,你可以看到这一点,但这个数字可以使我们的例子更容易!”)
2.计算分数。这与前面确定公钥的方法相同。为了简洁起见,我们省略了“相同点加倍”和“不同点相加”的算术计算。
(x,y)=3G
(x,y)=G 2G
(x,y)=(2,22) (52,7)
(x,y)=(62,63)
x=62
y=63
3.计算r。
r=x mod n
r=62 mod 79
r=62
4.计算s:
s=(z r d)/k mod n
s=(17 62 2)/3 mod 79
s=(17 124)/3 mod 79
s=141/3 mod 79
s=47 mod 79
s=47
注意,上面的计算中3可以整除,结果是整数。在实际计算中,我们需要用到k的倒数(和之前一样,我们隐藏了一些恶心的计算细节):
s=(z r * d)/k mod ns=(17 62 * 2)/3 mod 79s=(17 124)/3 mod 79s=141/3 mod 79s=141 * 3-1 mod 79s=141 * 53 mod 79s=7473 mod 79s=47
5.我们的签名是(r,s)=(62,47)。
像私钥和公钥一样,签名通常由十六进制字符串表示。
用公钥验证签名现在,我们有了数据和数据的签名。持有我们公钥的第三方组织可以接收数据和签名,并可以验证我们是发送者。让我们看看它到底是如何工作的。
q用来表示公钥,其他变量同上。验证签名的步骤如下:
1.验证r和s在1和n-1之间;
2.计算w=s mod n;
3.计算u=zw mod n;
4.计算v=rw mod n;
5.计算点(x,y)=ugvq;
6.验证r=x mod n,如果方程不成立,签名无效。
为什么这些步骤有用?我们省略了证明过程,但您可以从这里了解更多细节。
按照上面的方法,我们来看看验证过程是如何进行的。这些变量如下:
Z=17(数据)
(r,s)=(62,47)(签名)
N=79(订单)
G=(2,22)(基点)
Q=(52,7)(公钥)
1.验证r和s是否在1和n-1之间。
检查再检查
r: 1=62 79
学生:1=47 79
2.计算w:
w=s mod n
w=47 mod 79
w=37
3.计算u:
u=zw mod n
u=17 * 37 mod 79
u=629 mod 79
u=76
4.计算v:
v=rw mod n
v=62 * 37 mod 79
v=2294 mod 79
v=3
5.计算点(x,y):
(x,y)=uG vQ
我们将uG和vQ分解为“同点加倍”和“异点相加”,分别计算。
uG=76G
uG=2(38克)
uG=2( 2(19G))
uG=2( 2(G 18G))
uG=2( 2(G 2(9G)))
uG=2( 2(G 2(G 8G)))
uG=2( 2(G 2(G 2(4G))))
uG=2( 2(G 2(G 2( 2(2G))))
坐一会儿,意识到通过使用分组技巧,我们已经将75次连续加法运算减少到6次“同点加倍”和2次“不同点相加”。当数字变得非常大时,这些技能将会派上用场。
算出结果:
uG=2( 2(G 2(G 2( 2( 2(2,22)))))
uG=2( 2(G 2(G 2( 2(52,7))))
uG=2( 2(G 2(G 2(25,17))))
uG=2( 2(G 2( (2,22) (21,42))))
uG=2( 2(G 2(13,44)))
uG=2( 2( (2,22) (66,26)))
uG=2( 2(38,26))
uG=2(27,40)
uG=(62,4)
这是vQ:
vQ=3Q
2Q
vQ=Q 2(52,7)
vQ=(52,7) (25,17)
vQ=(11,20)
将两者相加:
(x,y)=uG vQ
(x,y)=(62,4) (11,20)
(x,y)=(62,63)
显然,第5步占了整个计算的大部分。最后一步是,
6.验证r=x mod n。
r=x mod n
62=62 mod 79
62=62
我们的签名是有效的!
结论对于那些看完了所有公式然后跳到最下面的读者来说,我们刚刚学到了什么?
我们对公钥和私钥之间的深层数学关系有了一些直观的认识。我们可以看到,即使在这个最简单的例子中,签名和验证的过程也立即变得非常复杂,所以我们可以意识到,一旦相关参数变成256位,复杂度将是多么巨大。我们看到了如何巧妙地应用最简单的数学运算,实现保护信息所需的单向“陷阱门”功能,定义了比特币的所有权。我们对系统的健壮性有了新的信心,只要我们能小心保护我们的私钥。
换句话说,这就是为什么人们常说比特币是“基于数学”的。
如果你能坚持阅读这些复杂的二进制位,我希望这能给你一些信心,让你采取下一步,并尝试自己做数学(这里有一个模块化计算器,可以让有限域的运算更容易)。我觉得手工对数据进行签名和验证,可以让人们更深刻地理解这种密码算法,这种算法塑造了比特币系统独特的“主人”形式。
本文转载自微信官方账号“数学中国”