1. 对message进行签名
from eth_account.messages import encode_defunct
from web3 import Web3
from eth_keys import keys
KEY = ... # 填写账户私钥
w3 = Web3(Web3.HTTPProvider(<input eth node url/>)) # 请填写以太坊的节点url
account = w3.eth.account.from_key(KEY)
print('address: ', account.address)
rawText = 'hello' # 签名message
signedMessage = account.sign_message(encode_defunct(text=rawText))
print('message hash: ', signedMessage.messageHash.hex())
# print(signedMessage)
print('v: ', int(signedMessage.v))
print('r: ', hex(signedMessage.r))
print('s: ', hex(signedMessage.s))
print('signature: ', signedMessage.signature.hex())
print(w3.eth.account.recover_message(encode_defunct(text=rawText), signature=signedMessage.signature))
2. 执行脚本,得到
address: 0x1c74c86906d91766e143e1d009C8604b66001363
message hash: 0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750
v: 28
r: 0x5a0121bea4f2c1e9e6aad76bd3e06191a533c0b53a77df31e3b6310dbf4f698f
s: 0x17216a4bfd7cf812bf2a6d9b44122c807880a5cb3de403d4baa8e0fb352189dd
signature: 0x5a0121bea4f2c1e9e6aad76bd3e06191a533c0b53a77df31e3b6310dbf4f698f17216a4bfd7cf812bf2a6d9b44122c807880a5cb3de403d4baa8e0fb352189dd1c
0x1c74c86906d91766e143e1d009C8604b66001363
3. 智能合约代码
pragma solidity ^0.8.13;
contract VerifySign{
//公匙:0x1c74c86906d91766e143e1d009C8604b66001363
//sha3(msg): 0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 (web3.sha3("abc");)
//签名后的数据:0x7eeb34fb6770d2b935de3657652e8060033ec47f57d10acbcc6a4b4d69f82db12d8ddd81e67a01a4a51a0e658760e895bab90a24cc0d7803800098be779ea1d91c
//将原始数据按段切割出来指定长度
function slice(bytes memory data, uint start, uint len) private returns (bytes memory) {
bytes memory b = new bytes(len);
for(uint i = 0; i < len; i++){
b[i] = data[i + start];
}
return b;
}
//bytes转换为bytes32
function bytesToBytes32(bytes memory source) private returns (bytes32 result) {
assembly {
result := mload(add(source, 32))
}
}
// "\x19Ethereum Signed Message:\n{{len}}"
function VerifyMessageV1(bytes32 messageHash, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address signer) {
signer = ecrecover(messageHash, _v, _r, _s);
}
address addr;
bytes32 r; bytes32 s; uint8 v;
function VerifyMessageV2(bytes32 messageHash, bytes memory signedString) public {
r = bytesToBytes32(slice(signedString, 0, 32));
s = bytesToBytes32(slice(signedString, 32, 32));
v = uint8(slice(signedString, 64, 1)[0]);
addr = ecrecover(messageHash, v, r, s);
}
function getSignCheckResult() public view returns (address _addr, bytes32 _r, bytes32 _s, uint8 _v){
_addr = addr;
_v = v;
_r = r;
_s = s;
}
}
4. 部署智能合约到remix
5. 执行VerifyMessageV1函数
输入参数:
{
"messageHash": "0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750",
"signedString": "28",
"_r": "0x5a0121bea4f2c1e9e6aad76bd3e06191a533c0b53a77df31e3b6310dbf4f698f",
"_s": "0x17216a4bfd7cf812bf2a6d9b44122c807880a5cb3de403d4baa8e0fb352189dd",
}
返回结果:
{
"signer": "0x1c74c86906d91766e143e1d009C8604b66001363",
}
signer和签名账户的地址一致
6. 执行VerifyMessageV2函数
输入参数:
{
"messageHash": "0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750",
"signedString": "0x5a0121bea4f2c1e9e6aad76bd3e06191a533c0b53a77df31e3b6310dbf4f698f17216a4bfd7cf812bf2a6d9b44122c807880a5cb3de403d4baa8e0fb352189dd1c",
}
执行getSignCheckResult,返回结果:
{
"_addr": "0x1c74c86906d91766e143e1d009C8604b66001363",
"_r": "0x5a0121bea4f2c1e9e6aad76bd3e06191a533c0b53a77df31e3b6310dbf4f698f",
"_s": "0x17216a4bfd7cf812bf2a6d9b44122c807880a5cb3de403d4baa8e0fb352189dd",
"_v": "28",
}
_addr和签名账户的地址一致