本帖最后由 powugzs 于 2023-5-18 20:17 编辑
以太坊签名采用了Keccak256取哈希值,以及secp256k1 椭圆曲线加密。
签名过程基本上是这样的:你有一个消息(在这种情况下,通常是一个交易),你使用你的私钥和这个消息来生成一个签名。然后,其他人可以使用你的公钥来验证这个签名。如果验证成功,那么他们可以确信这个消息是由持有相应私钥的人发送的,而且消息在传输过程中没有被篡改。这就是以太坊的签名算法如何工作的。
一、Keccak256
由于目前windows自带的api没有sha3的算法,无奈只能使用openssl去实现sha3-256算法了(sha3-256其实就是keccak256),但是openssl的sha3-256与以太坊所使用的sha3-256是有区别的,以太坊使用的是原始的 Keccak-256 算法,而不是 NIST定义的 SHA-3-256。openssl实现的是NIST定义的sha3算法。
到这里时是非常想放弃使用openssl的,但是看了大佬的文章,发现使用openssl是可以计算原始的keccak256哈希的,具体内容去看【利用openssl中的sha3生成以太坊账户地址_openssl keccak256_hnlylyb的博客-CSDN博客】。由于帖子内是定义了一个结构体,我测试了易语言得数据类型是无法达到目的得,所以采用指针去修改内存去实现。
变量名 | 类 型 | 静态 | 数组 | 备 注 | md | 整数型 | | | ctx | 整数型 | | | size | 整数型 | | | result | 字节集 | | | tmp | 整数型 | | |
size = 取字节集长度 (data )md = EVP_sha3_256 ()ctx = EVP_MD_CTX_new ()EVP_DigestInit (ctx, md )tmp = 指针到整数 (ctx + 12 )写到内存 ({ 1 }, tmp + 380, 1 ) EVP_DigestUpdate (ctx, data, size )result = 取空白字节集 (32 )EVP_DigestFinal (ctx, result, size )返回 (result )
二、secp256k1 椭圆曲线
说完了keccak256,接下来就是secp256k1曲线了,椭圆曲线ECDSA在openssl里面是有实现的,于是我兴致勃勃的开始了使用openssl去写签名部分。首先,openssl去写ECDSA的时候它的K值是随机的,以至于我们每次的签名值都不同,其实我一开始到这里的时候是想过放弃openssl的【经过测试,只要能拿到R,S,V值就可以做到恢复公钥的操作了】,所以无伤大雅 。
但是以太坊除了R,S值以外还多出来了一个V校验值,具体就是椭圆曲线计算时选择的点是R还是R’来决定V值是0还是1【以太坊又做了V=V+27处理】,可惜的是openssl并没有提供V值的获取函数,并且选择R时也是内部去做处理的。     
我真的是非常非常的无语的,已经测试了很多种方式也没有办法去计算出来V值,无非也就是用openssl去写一个恢复公钥去判断V值是1还是2吗,由于技术不太到位没能实现这一部分。
再次无奈,去下载了btc的secp256k1的cpp源码,去编译了dll地址贴在后面,到了这里的时候就十分之流畅了,它内置了k值得计算【插一句嘴,上面提到了k值,这个k值其实就是一个随机数】,但是现在市面上的大部分钱包都采用了【RFC 6979标准】,这里请自行百du我也没有去了解,总之大概就是使用私钥以及消息内容,去计算了这么一个k值,所以只要保证私钥以及消息不变得情况下,计算出来得签名即R,S,V值都是固定不变得。
最终这个签名算法在使用了openssl以及libsecp256k1后才写了出来,经过测试签名结果与小狐狸、web3.py结果一致。
【重点:由于libsecp256k1.dll涉及私钥,所以请大家自行编译libsecp256k1】
【重点:由于libsecp256k1.dll涉及私钥,所以请大家自行编译libsecp256k1】
【重点:由于libsecp256k1.dll涉及私钥,所以请大家自行编译libsecp256k1】
openssl【https://www.openssl.org/】
libsecp256k1【https://github.com/bitcoin-core/secp256k1】
|