Running into problems taking a signed message from Web3.js, and recovering the signing address in Web3.py.

Here is my code in JavaScript to create a signed message:

async function sign_message() {
    var message = "hi"
    var message_hash = web3.eth.accounts.hashMessage(message)
    //message_hash == 0x0d52783c4cbad7ebaf7eb943fc648f5282a52070442fc18d8dd16ddb2fcbaf66

    var accounts = await web3.eth.getAccounts()
    var signature = await web3.eth.personal.sign(message, accounts[0])
    //accounts[0] ~ 0x6d31165d5d932d571f3b44695653b46dcc327e84
    //signature == 0x29887fe718fcc6e64b97d681f80e6fd485883a45ec0dbc0e35a3752acf1065655d73c9034cac3df0dc82da015abe42367f5e90fd499d872b19610a3ea9c176921b

Then here is trying to recover the address in Python:

>>> message = "hi"
>>> message_hash = defunct_hash_message(text=message)
>>> message_hash
>>> signature = '0x29887fe718fcc6e64b97d681f80e6fd485883a45ec0dbc0e35a3752acf1065655d73c9034cac3df0dc82da015abe42367f5e90fd499d872b19610a3ea9c176921b'
>>> w3.eth.account.recoverHash(message_hash, signature=signature)

Note that the message_hash in both examples are the same, however recoverHash does not result in the correct Ethereum address.

I have used these two sources to try and help me debug the issue to no success:

How to properly sign a transction to be used by ecrecover?

Verifying personal.sign signature with pyethereum

  • What is the provider in web3.js? Different providers (may) implement the personal signature method differently.
    – carver
    Commented Jul 24, 2018 at 16:26
  • I was using Metamask (which in the back uses Infura I believe) as my Ethereum provider. I assumed that these calls had no dependency on Ethereum, simply the private key. Commented Jul 24, 2018 at 16:34
  • @carver is there some JavaScript code I can add which will guarantee me to be able to recover in Python? Or vice versa? Commented Jul 24, 2018 at 18:54

1 Answer 1


This is what ended up working:

async function create_signature(message, accounts) {
    var hex = ''
    for(var i=0;i<message.length;i++) {
        hex += ''+message.charCodeAt(i).toString(16)
    var hexMessage = "0x" + hex
    var signature = web3.eth.personal.sign(hexMessage, accounts[0])
    return signature

And on the Python side, we recovered the address like this:

def recover_address(message, signature):
    message_hash = defunct_hash_message(text=message)
    address = w3.eth.account.recoverHash(message_hash, signature=signature)
    return address

If anyone knows a better way to calculate the hexMessage in the JavaScript code, please respond with a comment!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.