1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| // SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /* 1. message to sign 2. hash(message) 3. sign(hash(message), private key) | offchain 4. ecrecover(hash(message), signature) == signer */
contract VerifySig {
// verify 验证签名函数 function verify(address _signer, string memory _message, bytes memory _sig) external pure returns(bool) {
bytes32 messageHash = getMessageHash(_message); // 对输入的消息进行 hash运算 bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash); // 对输入消息进行二次hash
return recover(ethSignedMessageHash, _sig) == _signer; // 判断公钥的地址是否与_signer 相等? }
function getMessageHash(string memory _message) public pure returns(bytes32) { return keccak256(abi.encodePacked(_message)); // 对消息进行hash运算 }
function getEthSignedMessageHash(bytes32 _messageHash) public pure returns(bytes32) { //在消息中加入 "\x19Ethereum Signed Message:\n32" 字符串,将该字符串和 _messageHash 打包并进行hash运算 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) = _split(_sig); // 将_sig 分割为 r, s, v三个部分 return ecrecover(_ethSignedMessageHash, v, r, s);
}
function _split(bytes memory _sig) internal pure returns(bytes32 r, bytes32 s, uint8 v) { require(_sig.length == 65, "invalud signature length");
assembly { // add(_sig, 32) 指跳过32位长度, 去获取_sig 中的一个32位数据 r := mload(add(_sig, 32))
// add(_sig, 64) 指跳过64位长度, 去获取_sig 中的一个32位数据 s := mload(add(_sig, 64))
// add(_sig, 96) 指跳过96位长度, 去获取_sig 中的一个32位数据 // byte(0, mload(add(_sig, 96))) 返回32位中的第一个值 v := byte(0, mload(add(_sig, 96))) } } }
|