创建并打包原始消息
原始消息:”Hello, Web3.”
消息哈希:0xb0a90a95a2e95f53bc8a27629ce3d3b8c32507b1889e418e308b4ecb0d01554c
生成以太坊签名哈希
签名哈希:0x8eea87c68554dc0b647493d38a4b53aeea63c6841b10290714ff5f65ff08f2d5
Metamask签名消息
打开浏览器前端console,输入
ethereum.send('eth_requestAccounts') account = "以太坊签名账户地址" hash = "消息哈希" ethereum.request({method: "personal_sign", params: [account, hash]})
得到签名:
0x7ac68849793e559e457718a22f0b122ec3f9c94ed2a5163283d6a55d3c3c32c05e2eaeaa81766fe6c6ce82e971f66a943a7dfa34a9f3d40ede2fb66ea4d698b01c
验签
使用签名地址、以太坊签名哈希、签名,验签
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.2 <0.9.0;
contract test {
function getMessageHash(string memory message) public pure returns(bytes32) {
return keccak256(abi.encodePacked(message));
}
function getEthSignedMessageHash(bytes32 _messageHash) public pure returns(bytes32) {
return keccak256(
// 这是标准字符串: \x19Ethereum Signed Message:\n
// 32 表示后面的哈希内容长度
abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash)
);
}
function recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature) public pure returns (address) {
(bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);
// 返回解析出来的签名地址
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");
// 通过读取内存数据 根据规则进行截取 返回 r, s, v 数据
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := byte(0, mload(add(sig, 96)))
}
}
function verify(bytes32 _ethSignedMessageHash, bytes memory _signature, address _signer) public pure returns(bool) {
return recoverSigner(_ethSignedMessageHash, _signature) == _signer;
}
}
