unable to verify a signed message in solidity

I am using this tutorial: https://web3py.readthedocs.io/en/stable/web3.eth.account.html

##  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'))

When I pass these params such as signed_message.messageHash and signed_message.signature to the recoversigner(mentioned below) function in the smart contract. It gives the correct address. But when I am passing arguments tokens, contractaddress (used above) to the solidity keccak256(abi.encodePacked(token,address(this))) генерируемое сообщение отличается от signed_message.messageHash и, в свою очередь, я получаю другой адрес на выходе из ecrecover.

Я проверил, какой результат keccak256(abi.encodePacked(..)). Я обнаружил, что это то же самое, что и значение sig

Что я сделал:

  1. Сделайте токен ERC20.

  2. настроить канал

Моя цель:

  1. подписывать сообщения (с помощью web3py)

  2. убедительно подтвердите подписанное сообщение.

Нравится:

Пользователь передаст некоторые аргументы: например, адрес контракта и количество токенов вместе с подписанным сообщением. и я подтвердю это с помощью

    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))));

Это не работает должным образом. Я не получаю правильный адрес в качестве вывода.

Пожалуйста помоги..

1 ответ

Решение

Я не совсем понимаю, что вы пытаетесь сделать, но важное уточнение здесь заключается в том, что Web3 eth.sign (и его базовый вызов JSON-RPC eth_sign) не подписывайте простой хеш. Он добавляет строку префикса со встроенной длиной.

Увидеть eth_signдокументы:

Метод подписи вычисляет специальную подпись Ethereum с помощью: sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))).

Добавляя префикс к переданному сообщению, ваш клиент гарантирует, что вы не используете eth_sign для подписания транзакции (предположительно случайно или в результате атаки).

Вызов recoverHash(sig, ...)это вроде бессмысленно. Хотя переменная называется "sig", это просто хэш каких-то данных - он ничем не подписан.


Если вы разрабатываете новую схему подписи сообщений, я настоятельно рекомендую использовать какой-нибудь стандарт. Если вам нужен самый простой вариант, вы можете использовать сообщение EIP-191"Версия 0".

Для этого вы можете использовать eth-account's 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)
Другие вопросы по тегам