DEV Community

auok007
auok007

Posted on

ECDSA使用,实现多签 (一)

ECDSA在前面的文章已经提到,尝试爆破NFT奖励时间限制 (二)
这方面的原理,以及实现我就不讨论了,文章比较多,程序员嘛,除了自己写的代码,就是关注接口,学会要会使用。

文档

我这里使用的openzeppelin的实现,大家可以看看这里的文档。

FUNCTIONS
    tryRecover(hash, signature)
    recover(hash, signature)
    tryRecover(hash, r, vs)
    recover(hash, r, vs)
    tryRecover(hash, v, r, s)
    recover(hash, v, r, s)
    toEthSignedMessageHash(hash)
    toEthSignedMessageHash(s)
    toTypedDataHash(domainSeparator, structHash)
Enter fullscreen mode Exit fullscreen mode

加密中比较重要的,私钥,公钥,信息

签名:

  1. 钱包用私钥,
  2. 信息 hash,
  3. 生成签名。

验证签名:

  1. 信息生成公钥hash
  2. 信息 hash recover 签名,得到签名的公钥地址
  3. 比较公钥地址一致,说明是这个地址签名的

代码

直接来个测试用例,说明这个过程,里面的私钥都来自Ganache公开的私钥
,测试使用环境用的forge,不会用forge,看这里forge 入门

function testSign() public {
        address alice = address(0x9BEF5148fD530244a14830f4984f2B76BCa0dC58); //alice的公钥
        address bob = address(0x8Aa8b0D84cf523923A459a6974C9499581d1F93D); //bob的公钥
        bytes32 hash = keccak256("Signed by Alice"); //信息hash值
        (uint8 v, bytes32 r, bytes32 s) = sign(
            0x18ef5d5e78aa58a63503bcb48a563de61ffe7665d73ee22b4ab66ef15248be5a,
            hash
        ); //使用的alice的私钥、hash进行签名
        bytes memory sig = abi.encodePacked(r, s, v); //打包成测试需要的格式
        address signer = hash.recover(sig); //使用的ECDSA recover 函数得到签名地址
        emit log_named_address("address", signer);
        assertEq(alice, signer);
        (uint8 v2, bytes32 r2, bytes32 s2) = sign(
            0x4e1518672e45fb2746ec5a217330ed24d815d44537da647e973c06d0b0069053,
            hash
        ); //bob的私钥
        bytes memory sig2 = abi.encodePacked(r2, s2, v2);
        address signer2 = hash.recover(sig2);
        emit log_named_address("address", signer2);
        assertEq(bob, signer2);
    }
Enter fullscreen mode Exit fullscreen mode

就这样,做多签的基础就有了。

下一篇就讲讲怎么做到多签名确认,才能转账。
上面的代码对forge-std加了一个小函数。

function sign(uint256 pri, bytes32 msg)
        public
        returns (
            uint8,
            bytes32,
            bytes32
        )
    {
        return vm_std_cheats.sign(pri, msg);
    }
Enter fullscreen mode Exit fullscreen mode

更详细的,看我github上的仓库,后面的多签,也会提交到这里:
SimpleMultiSig

Discussion (0)