Solidity 验证签名

Solidity有一个ecrecover 指令,可以根据消息hash 和签名,返回签名者的地址:

ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)
根据恢复的签名地址,与验证地址对比,就可以验证签名。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Signature {
   function verify(address _signer, string memory _message, bytes memory _signature) 
   external pure returns(bool) {
      bytes32 hash = getHash(_message);
      bytes32 ethSignedHash = getEthHash(hash);
      return recover(ethSignedHash,_signature) == _signer;
   }
   
   function getHash(string memory _message) public pure returns(bytes32) {
      return keccak256(abi.encodePacked(_message));
   }

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

   function recover(bytes32 ethSignedHash, bytes memory _signature) public pure returns(address) {
      (bytes32 r, bytes32 s, uint8 v) = _split(_signature);
      return ecrecover(ethSignedHash, v, r, s);
   }

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