1

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
    console.log(signature)
    //signature == 0x29887fe718fcc6e64b97d681f80e6fd485883a45ec0dbc0e35a3752acf1065655d73c9034cac3df0dc82da015abe42367f5e90fd499d872b19610a3ea9c176921b
}

Then here is trying to recover the address in Python:

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

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 Jul 24 '18 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. – Shawn Tabrizi Jul 24 '18 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? – Shawn Tabrizi Jul 24 '18 at 18:54
0

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, privacy policy and cookie policy

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