Search code examples
pythonethereumdigital-signatureecdsametamask

Verify Metamask signature (ethereum) using Python


I would like to verify an ethereum (ETH) signature made in MetaMask using python. I'm developing a website using flask as backend. Javascript code send a POST requests to the back end containing the 3 following variables:

{'signature': '0x0293cc0d4eb416ca95349b7e63dc9d1c9a7aab4865b5cd6d6f2c36fb1dce12d34a05039aedf0bc64931a439def451bcf313abbcc72e9172f7fd51ecca30b41dd1b', 'nonce': '6875972781', 'adress': '0x3a806c439805d6e0fdd88a4c98682f86a7111789'}

My goal is to verify that the signature contains the nonce (random integer) and was sign by the public adress

I using javascript to sign the nonce using the ether library

const ethereum = window.ethereum;
const provider = new ethers.providers.Web3Provider(ethereum)
const signer = provider.getSigner()
var signature = await signer.signMessage(nonce);

I tried with several python libraires, but I'm unable to format signature, adress and nonce so that it works. here is unsuccessfull try made using ecdsa librairy:

vk = ecdsa.VerifyingKey.from_string(bytes.fromhex(address), curve=ecdsa.SECP256k1, hashfunc=sha256) 
vk.verify(bytes.fromhex(hex(signature)), bytes(nonce, 'utf-8'))

I get the following error:

ValueError: non-hexadecimal number found in fromhex() arg at position 1

Thanks for your help !


Solution

  • Using web3.py you could use w3.eth.account.recover_message to recover the address from the signature and the data. After that you compare the adress to the correct adress(with lowercase, because i think web3.py would give you lower and uppercase)

    from web3 import Web3
    from hexbytes import HexBytes
    from eth_account.messages import encode_defunct
    w3 = Web3(Web3.HTTPProvider(""))
    mesage= encode_defunct(text="6875972781")
    address = w3.eth.account.recover_message(mesage,signature=HexBytes("0x0293cc0d4eb416ca95349b7e63dc9d1c9a7aab4865b5cd6d6f2c36fb1dce12d34a05039aedf0bc64931a439def451bcf313abbcc72e9172f7fd51ecca30b41dd1b"))
    print(address)