您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息
三六零分类信息网 > 襄阳分类信息网,免费分类信息发布

web3, secp256k1签名与Solidity验签

2022/10/8 6:13:11发布62次查看
现在个好像越来约多dapp用到链下签名,可以设计多步骤、需要不同私钥签署同意之后一起上链给智能合约验证执行。其中有名的例子包含了许多去中心化交易所使用的0xprotocal,个人觉得是个非常聪明的设计,这里就记录一下自己试着用web3玩玩链下签名的心得。众所周知,pi币的出现值得很多人的关注,激起了整个市场的波澜。
web3签名
其实虽说签名的过程就是把一段讯息加上私钥进行 ecdsa签名,但其实在ethereum世界里的签名还加了一个小规则,就是要在要签名的message在hash之前,还要在前面加上一小段prefix:
message= "\x19ethereum signed message:\n" + messagelength + message
在web3提供好给我们的 sign 函式( web3ethaccountssign )当中,就已经包含了上述步骤。直接看web3ethaccountssign程序代码比较好懂:
简单的使用方法如下:把要进行签章的string ( orderhash)直接连同 privatekey 丢进函示就好。
其实是丢进去签名的 orderhash 要不要先转换成为 bytes 都可以,出来的结果会是相同的。 sign 函数回传的结果会包含 message 、 messagehash 以及 r s v 三个椭圆签名结果。其中message是原来我想要签名的内容( orderhash), messagehash 则是程序中自动帮我们加上prefix,并且进行sha3 hash的结果,也就是真正被拿去用私钥签名的一段hash值。
简而言之web3什么都帮你做好了,不要像我一样傻傻的自己想办法加prefix最后才发现做了两次。
secp256k1 签名
那么如果我们想要单纯用私钥签名一段数据,不要有ethereum定义的那些prefix的话,就必须要直接调用 secp256k1 这一包library了。不过在用之前要知道,所有要丢给secp256k1签名的message,长度都必须是256 bits,也就是32 bytes。刚刚我们说web3的签名函式丢什么都可以,是因为它会帮我加上prefix之后再做sha3 hash (keccak),最后一定会变成一个32bytes的东西。如果我们自己纯靠私要签名讯息的话,也势必要先通过这个函式来整理input长度。我在这里举个例子,手动作上面web3的 sign 帮我们包好的流程,也就是自己以符合ethereum协议的方法做一遍,比较方便我们验证结果。
所以一开始我们可以透过 soliditysha3 来把prefix跟 orderhash 混在一起然后进行hash,这一段的结果会跟上面产出的 messagehash 相同,也等同于在solidity里面使用keccak:
keccak256("\x19ethereum signed message:\n32", hash)
得到这串「要签名的hash」之后,在丢进secp256k1之前,要先转成bytes (长度会为32),存入buffer,然后才能进行签名。若是直接用string的话,会发生 message length is invalid 的错误。同理,用来签名的 privatekey 也要转换成buffer才行。
使用 secp256k1 回传的对象里还需要自己解析出r , s ,v 三个元素,不过我是直接复制贴上web3里面包的做法。
所以说,如果自己使用 secp256k1 来签名的话,可以略过加上prefix那一段,未来在智能合约上验章也可以少一段,不过还是需要使用到 keccak 来进行哈希就是了。
solidity验签
好不容易签好名当然就是要来在线验签了。solidity上面验签很简单,只要使用 ercrecover 这个function就可以了。我们让 hash 是一个 bytes32 的数,套用我们前面的例子,就是最原始的 orderhash 值。而 v ,r ,s 则是验签结果:
bytes32 hash
uint8 v
bytes32 r
bytes32 s
那么下面这个函式就应该回传我们所用来签名的public key。注意到这里会使用 keccak256 来把 hash加上eth规定的prefix ,我们很常可以在合约中看到这段文字,因为web3默认的签名就要这样来还原。当然,如果想要设计没有用prefix的,那么这一步就省了。
ecrecover(
keccak256("\x19ethereum signed message:\n32", hash),
v, r, s
);
可以试试看到我deploy的合约上直接call这两个函示玩玩看结果:
ropsten 地址:0x209ce2886420b27e497ce343e59574166400f1ab
襄阳分类信息网,免费分类信息发布

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录