验证签名的步骤:
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签名信息

