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
Что я сделал:
Сделайте токен ERC20.
настроить канал
Моя цель:
подписывать сообщения (с помощью web3py)
убедительно подтвердите подписанное сообщение.
Нравится:
Пользователь передаст некоторые аргументы: например, адрес контракта и количество токенов вместе с подписанным сообщением. и я подтвердю это с помощью
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)