加工设备
7163银河_一个数字引发的探索
FISCO BCOS交易亲笔签名算法基于ECDSA原理展开设计,ECDSA也是比特币和以太坊使用的交易亲笔签名算法。本文讲解ECDSA及椭圆曲线加密(ECC)涉及科学知识、ECDSA的Recover机制和构建方式、FISCO BCOS交易亲笔签名和验签的底层原理。
内容稍软(shu)核(xue),青睐对密码学原理、区块链底层原理感兴趣的开发者一起交流。故事开始故事要从以太坊中一个神秘的魔数开始想起。以太坊黄皮书中,关于交易亲笔签名的阐释谈到两个类似的数「27,28」,实质上就是指「0,1」通过特了一个27演进获得「27,28」,所以本质上是一个类似的数27。
这个类似的数字27代表了什么含义呢?一次刑警之旅开始了…这看起来一个bug搜寻找到此前有数许多关于该问题的辩论,其中,Stack Exchange的一篇帖子认为这是一个设计bug。以太坊源码github上,也有一个涉及issue,该issue被印上了「type:bug」的标签。Stack Exchange帖子中有一个链接得出了修缮该Bug的代码,请求看下面图片(红框)。
在注解解释和代码可见,fromRpcSig函数对27这个魔数展开了类似处置。从RPC过来的亲笔签名中,v值如果大于27(有可能是0-3),则必要再加27作为新的v值,fromRpcSig函数通过这个方式相容ECDSA完整v值(也就是recoveryID)和以太坊v值。这感叹以太坊设计的一个bug吗?返回刚才那个fromRpcSig的源代码文件,详尽看其各模块构建,我们找到有这样一行代码「v: chainId ? recovery + (chainId * 2 + 35) : recovery + 27」,这不道德v赋值的代码透漏了三个信息,分别是魔数27、魔数35和ChainID。
于是,疑惑更加多了,魔数35是什么?ChainID又是什么?这不看起来一个Bug带着这些疑惑,再行一次查询涉及设计材料,我们看见,以太坊EIP155中叙述了有关ChainID的设计。基于以太坊源码建构的网络,实际运营的链有很多,网卓新闻网,为了避免一条链的交易被递交上链到另一条链,导致纠错反击,引进了ChainID的设计,在块低2,675,000的方位展开末端构建。
明白了ChainID的起到,另一个疑惑又产生了——以太坊中,有NetworkID来区分有所不同网络,为什么还必须ChainID?这要从NetworkID和ChainID的起到范围来说明。NetworkID主要在网络层面展开链的隔绝,节点在创建相互连接的时候必须互相交换NetworkID,享有完全一致的NetworkID才能已完成问候相连。ChainID是交易层面,避免有所不同网络的交易被交叉反复反击。以太坊(ETH)和经典以太坊(ETC)的主网NetworkID都是1,必须通过 ChainID机制才能避免交易在ETH和ETC网络之间交叉纠错,ETH主网的ChainID是1,ETC主网的ChainID是61。
说道到这里只不过还是没搞清楚为什么是27,为什么是35?我们在EIP github的Issue#155中看见Jan和Buterin的交流记录,显然27是来自比特币的产物。顺藤摸瓜,关上electrum的github,我们在electrum/electrum/ecc.py中寻找如下代码从代码中可见,electrum在亲笔签名时,为原本只有0-3之间的recid(recoveryID)再加了27,还有一个传输标记,如果有传输则再行再加4,recid的值范围在27-34。自此由此可知,27和35大约源于此,以太坊承继比特币的设计,在比特币源码bitcoin/src/key.cpp的CKey::SignCompact函数中也确认了该构建方式,但是比特币为什么如此设计,仍未可知。ECDSA才是“bug”故事到这里,我们对以太坊代码中那个魔数27的前世今生有大约理解,但这意味着是故事的开端,由此引起我们更进一步思维一个问题:recoveryID是什么?为了说明确切这个问题,我们必须从ECDSA算法著手,从数学角度解读其背后的原理。
ECDSA是FISCO BCOS使用的交易亲笔签名算法,由此我们不会找到,ECDSA算法有一种Recover机制,它才是确实“bug”级别的功能。ECDSA(Elliptic Curve Digital Signature Algorithm)是基于椭圆曲线的数字签名算法。
数字签名算法是使用公私钥体系构建类似于写出在纸上的普通亲笔签名,用作辨别数字信息的方法,少见的数字签名算法还包括DSA、RSA和ECDSA等。椭圆曲线密码(ECC)是基于椭圆曲线数学的公钥加密算法,创建在椭圆曲线线性对数艰难问题之上,常用的协议有ECDH、ECDSA和ECIES等。
椭圆曲线的参数可以有多种配备方式,也就不存在多种不同的曲线,例如secp256k1、secp256r1、Curve25519等,有所不同曲线的安全性不存在一些区别,在SafeCurves中有涉及对比叙述。ECDSA算法主要还包括以下四个关键功能:产生密钥GenKey· 自由选择一条椭圆曲线E_P(a,b),自由选择基点G,G的阶数为n· 自由选择随机数d ∈n为私钥,计算出来公钥Q = d⋅G亲笔签名算法Sign· 对消息m用于消息概要算法,获得z=hash(m)· 分解随机数k∈n,计算出来点(x, y)=k⋅G· 所取r=x mod n,若r=0则新的自由选择随机数k· 计算出来s = k^−1(z+rd) mod n,若s=0则新的自由选择随机数k· 上述(r,s)即为ECDSA亲笔签名检验算法Verify用于公钥Q和消息m,对亲笔签名(r,s)展开检验。· 检验r,s∈n· 计算出来z = hash(m)· 计算出来u_1 =zs^−1 mod n和u_2 = rs^−1 mod n· 计算出来(x, y) = u1⋅G+u2⋅Q mod n· 辨别r == x,若大于则亲笔签名检验顺利完全恢复算法Recover未知消息m和亲笔签名(r,s),完全恢复计算出来出有公钥Q。
· 检验r, s∈n· 计算出来R=(x, y),其中x=r,r+n,r+2n...,代入椭圆曲线方程计算出来取得R· 计算出来z = hash(m)· 计算出来u_1 = −zr^−1 mod n和u_2 = sr^−1 mod n· 计算出来公钥Q= (x’, y’)=u_1⋅G+u_2⋅R为了问recoveryID的问题,我们重点注目「完全恢复算法Recover」。在计算出来R的步骤可以看见,不存在多个x的给定可能性,造成不存在多个R的可能性,因此计算出来获得的Q也不存在多个有可能的结果,必须通过和未知的公钥对比,确认哪一个Q是准确的。
如果迭代x的所有有可能都未找到准确的Q,解释该消息和亲笔签名是不对应的,或者是一个不得而知的公钥。为了确认准确的Q,必须迭代x的所有有可能给定,跑完多轮Recover算法,这个时间支出是较为大的。为了提升Recover的时间效率,使用空间换时间的思路,在亲笔签名中减少一个v值,用作较慢确认x,防止迭代查询试探,这个v值就是recoveryID。
在区块链系统中,客户端对每笔交易展开亲笔签名,节点对交易亲笔签名展开检验。如果使用「检验算法Verify」,那节点必需首先告诉发给该交易所对应的公钥,因此必须在每笔交易中装载公钥,这必须消耗相当大比特率和存储。如果使用「完全恢复算法Recover」,并且在分解的亲笔签名中装载recoveryID,就可以较慢完全恢复出有发给该交易对应的公钥,根据公钥计算出来出有用户地址,然后在用户地址空间继续执行适当操作者。
这里潜藏了一个区块链设计哲学,区块链上的资源(资产、合约)都是归属于某个用户的,如果需要结构出有合乎该用户地址的亲笔签名,等同于掌控了该用户的私钥,因此节点需要事前确认用户公钥,仅有从亲笔签名完全恢复出有公钥,进而计算出来出有用户地址,就可以继续执行这个用户地址空间的适当操作者。FISCO BCOS基于这个原理设计构建了交易亲笔签名和验投。recoveryID的计算出来关于JavaSDK性能优化的文章(记一次JavaSDK性能从8000提高至30000的过程)中提及一个关键优化点——recoveryID的计算出来,这里细心展开讨论。
ECDSA亲笔签名(r,s),其中r是椭圆曲线上一个点kG (x, y)对应的x mod n,相等于亲笔签名信息中只留给了X轴座标涉及的值,弃置了Y轴涉及的值。在「完全恢复算法Recover」中尝试寻回Y轴对应的值结构R,进而完全恢复出有公钥。由于r = x mod n,因此r,r+n,r+2n…都有可能是合法的完整x值,有所不同的椭圆曲线不存在有所不同数量这样合法的x值,FISCO BCOS使用的secp256k1曲线不存在两个有可能r, r+n。
每一个X轴座标对应两个有可能的Y座标,因此FISCO BCOS中不具备四种有可能的R,(r, y) (r, -y) (r+n, y’) (r+n, -y’)。但是,对于一个r值不存在两个X轴座标的概率极低,较低到完全可以忽视,以太坊中就忽视了这两种小概率事件。
那这个小概率事件的概率明确有多小呢?这要从secp256k1曲线的参数想起,一般来说叙述一个椭圆曲线的点(x,y)的时候,x和y的值是 mod p 的结果,p是曲线的参数,它是一个大素数,之前提及的n也是曲线的参数,相等这条曲线上点的数量(曲线上点的数量为n*h,h也是曲线参数,该曲线h=1),在secp256k1中,n和p的值十分相似,明确可见右图。
本文关键词:7163银河
本文来源:7163银河-www.argylehuzhou.cn