Cover photo

验证签名

验证签名的步骤:

1、 将消息message 转换成 sign

2、对message进行hash处理

3、sign(hash(message), private key) | offchain

4、ecrecover(hash(message), signature ) == signer

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract VerifySig{

    function verify(address _signer, string memory _message, bytes memory _sig) external pure returns(bool){
        bytes32 messageHash = getMessageHash(_message);
        bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);

        return recover(ethSignedMessageHash, _sig) == _signer;
    }

    function getMessageHash(string memory _message) public pure returns(bytes32){
        return keccak256(abi.encodePacked(_message));
    }

    function getEthSignedMessageHash(bytes32 _messageHash) public pure returns(bytes32){
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash));
    }

    function recover(bytes32 _ethSignedMessageHash, bytes memory _sig) public pure returns(address){
        (bytes32 r, bytes32 s, uint8 v) = splitSignature(_sig);
        return ecrecover(_ethSignedMessageHash, v, r, s);
    }

    function splitSignature(bytes memory sig) public pure returns(bytes32 r, bytes32 s, uint8 v){
        require(sig.length == 65, "invalid signature length");
        assembly {
            r := mload(add(sig, 32))
            s := mload(add(sig, 64))
            v := byte(0, mload(add(sig, 96)))
        }
    }
}

第一步: 首先对消息进行hash处理,主要使用的keccak256处理消息的字节码

第二步:线下使用metamask,对第一步字节码和EOA账号进行签名,使用的方法是:

         签名信息 = ethereum.request({method: "personal_sign", params: \[account, hash\]})

第三步:将第二步生成的签名进行恢复

     首先使用ethHash = getEthSignedMessageHash(第一步生成的字节码)

 EOA账号信息 = recover(ethHash,签名信息 )

这时,可以比对看看是不是和EOA账号相同???

第四步: 使用verify方法,检测sign是否有效

 bool res2 = sig.verify(user, _message, SigRes);
user: EOA账号
_message: “实际的加密信息”
SigRes: metamask签名信息