# Eth智能合约签名校验 - 可用于实现多签合约 **Published by:** [zhongxuqi](https://paragraph.com/@zhongxuqi/) **Published on:** 2023-01-31 **URL:** https://paragraph.com/@zhongxuqi/eth ## Content 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. 部署智能合约到remixhttps://remix.ethereum.org/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和签名账户的地址一致 ## Publication Information - [zhongxuqi](https://paragraph.com/@zhongxuqi/): Publication homepage - [All Posts](https://paragraph.com/@zhongxuqi/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@zhongxuqi): Subscribe to updates