【问题标题】:Can't validate authenticated message with ECDSA.recover无法使用 ECDSA.recover 验证经过身份验证的消息
【发布时间】:2021-12-03 03:35:13
【问题描述】:

我需要能够从合同中检索文档,让用户钱包对其进行签名,然后将其发送回合同并验证签名。

下面是我让 address0 在客户端签名的方法:

   let message : string = "check this message signed by account0";
   let messageHash = keccak256(utils.toUtf8Bytes(message));
   let signature = await address0.signMessage(messageHash);
   await hm.connect(address0).verifyMessage(message, signature);

这是我合约中的验证器:

   function verifyMessage(string memory message, 
      bytes memory signature) 
      public view  returns(bool) {
      
        //hash the plain text message
        bytes32 messagehash =  keccak256(bytes(message));
        //hash the prefix and messagehash together   
        bytes32 messagehash2 = keccak256(abi.encodePacked("\x19Ethereum Signed Messsage:\n32", messagehash));
        //extract the signing contract address
        address signeraddress = ECDSA.recover( messagehash2, signature);
        if (msg.sender==signeraddress) {
            //The message is authentic
            return true;
        } else {
            //msg.sender didnt sign this message.
            return false;
        }
    }

很遗憾,ECDSA.recover 为 signeraddress 返回的值不是 account0 的地址,尽管有很多 经过实验,我无法从签名中推导出消息发件人的正确地址。

不胜感激。

【问题讨论】:

    标签: solidity ecdsa ethers.js hardhat


    【解决方案1】:

    我能够从 Openzeppelin 上的人们那里得到答案。

    如果任何其他机构遇到这种情况,一个问题是计算哈希和在客户端计算签名的方式

    代替

       let messageHash = keccak256(utils.toUtf8Bytes(message));
    

    使用

        let messageHash = ethers.utils.solidityKeccak256(['string'], [message]);
    

    而不是

        let signature = await address0.signMessage(messageHash);
    

    使用

         let signature = await address0.signMessage(ethers.utils.arrayify(messageHash));
    

    在服务器端,可以使用 `ECDSA.toEthSignedMessageHash() 更简单地添加前缀,如下面的解决方案:

    using ECDSA for bytes32; 
    
    function verifyMessage(string memory message, bytes memory signature) public view  returns(address, bool) {
            //hash the plain text message
            bytes32 messagehash =  keccak256(bytes(message));
           
            address signeraddress = messagehash.toEthSignedMessageHash().recover(signature);
                  
            if (msg.sender==signeraddress) {
                //The message is authentic
                return (signeraddress, true);
            } else {
                //msg.sender didnt sign this message.
                return (signeraddress, false);
            }
        }
      
    
        
    

    【讨论】:

      猜你喜欢
      • 2019-09-25
      • 2010-11-17
      • 1970-01-01
      • 2021-05-26
      • 1970-01-01
      • 1970-01-01
      • 2012-09-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多