繁体   English   中英

无法可靠地验证签名的消息

[英]unable to verify a signed message in solidity

我正在使用本教程: https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-message

##  in web3py

sig = Web3.soliditySha3( [uint256, address], [tokens, contractaddress] ) ## used below also
output: HexBytes('0x3efb3cf4e41109f6f1f998401d02dbe894719a8806f45e79a5fab7d4799f00bb')
from eth_account.messages import encode_defunct
msg = sig.hex()
message = encode_defunct(text=msg)
signed_message = w3.eth.account.sign_message(message, private_key=private_key)
signed_message

SignedMessage(messageHash=HexBytes('0x4c0c7077f770069785167e8b7451d63fad1e858ef5251b239eb0781c314000d2'), r=5665764915496639843348851536709769469640799172147461427941649091688603148258, s=48121517563314450138554207713326165180739298862566159641495137088718857193470, v=27, signature=HexBytes('0x0c86b594baa5bb06a0f4054ffdf3896377cfb757d42dcaeacf0241d96a4d5fe26a63d0514338ec600c89ee808dc088e7b3aadc55b9f5d86685d3ff212e2e47fe1b'))

当我将这些参数(如signed_message.messageHashsigned_message.signature )传递给智能合约中的recoversigner(如下所述)function 时。 它给出了正确的地址。 但是当我将 arguments tokens, contractaddress传递给keccak256(abi.encodePacked(token,address(this)))时,生成的消息与signed_message.messageHash不同,反过来我得到一个不同的地址作为来自 ecrecover 的ecrecover

我检查了keccak256(abi.encodePacked(..))的 output 是什么。 我发现它与 sig 值相同

我做了什么:

  1. 制作 ERC20 代币。

  2. 设置频道

我的目标:

  1. 签署消息(使用 web3py)

  2. 用solidity验证签名的消息。

像这样:

用户将传递一些 arguments:如合约地址和代币数量以及签名消息。 我将验证它

    function splitSignature(bytes memory sig)
        pure
        internal
        returns (uint8 v, bytes32 r, bytes32 s)
    {
        require(sig.length == 65 , "invalid length");

        assembly {
            r := mload(add(sig, 32))
            s := mload(add(sig, 64))
            v := byte(0, mload(add(sig, 96)))
        }
        if (v < 27) {
            v += 27;
        }

        require(v == 27 || v == 28 , "value of v ");
        return (v, r, s);
    }

    function recoverSigner(bytes32 message, bytes memory sig)
        internal 
        pure
        returns (address)
    {
        (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig);
        return ecrecover(message, v, r, s);
    }

bytes32 message = prefixed(keccak256(abi.encodePacked(token,address(this))));

这无法正常工作。 我没有得到正确的地址 output。

请帮忙..

我并不完全清楚您要做什么,但这里要澄清的一个重要问题是 Web3 的eth.sign (及其底层 JSON-RPC 调用eth_sign )不会签署简单的 hash。 它添加了一个前缀字符串,其中嵌入了一个长度。

请参阅eth_sign文档

sign 方法使用以下公式计算以太坊特定的签名: sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)))

通过向传递的消息添加前缀,您的客户端可以确保您没有使用eth_sign来签署交易(可能是偶然的,或者由于攻击)。

调用recoverHash(sig, ...)有点荒谬。 尽管该变量称为“ sig ”,但它只是一些数据的 hash ——它没有被任何人签名。


如果您正在设计一个新的消息签名方案,我强烈建议您使用某种标准。 如果您想要最简单的选项,您可以使用EIP-191的“版本 0”消息。

为此,您可以使用 eth-account 的encode_intended_validator() ,它看起来像:

from eth_account.messages import encode_intended_validator
message = encode_intended_validator(YOUR_CONTRACT_ADDR, sig)
signed_message = w3.eth.account.sign_message(message, private_key=private_key)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM