Ethers.js: How do I use verifyMessage with binary data?

Created on 22 Feb 2019  路  2Comments  路  Source: ethers-io/ethers.js

I am converting my tests from web3.js to ethers.js for redundancy. Web3JS signatures are compatible with openzeppelin, but ethers.js is not.

I've noticed there are some differences in how each package perform signature verification and am curious what is the explanation.

My use case is to send signed parameters to be verified on chain using openzeppelin's ECDSA

Solidity

contract Verification is ECDSA {
    function getRecover(bytes32 sigHash, bytes memory sig) public pure returns (address) {
        return sigHash.toEthSignedMessageHash().recover(sig);
    }
}

Test

// Parameters
sigHash = '0x648978d27edc284b1a72048fdeb2147d5292601d09ba43b3fb29ca0307777d9e'
user.address = '0xD9995BAE12FEe327256FFec1e3184d492bD94C31'
user.privateKey = '0x7ab741b57e8d94dd7e1a29055646bafde7010f38a900f55bbd7647880faa6ee8'

// Compute signatures
let sigEJS = await user.signMessage(sigHash)
let sigWJS = (web3.eth.accounts.sign(sigHash, user.privateKey)).signature

sigEJS --> '0x8db049dbdd96c030a1723a057e6ca5aa2298764249eabd9d6a13040d5c526c9f23e0c6607eda80f96af6a1f26d669e2412fe356fbc7556cb71686a97556bba581c'
sigWJS --> '0xdc8b5fe7a3174d1f3aa38175893dcacc15c2bdfce71126576b4395a9b96e3600593bdc3af47f7b8592a7bb1540e546945986080a85f9ecf48ae746a709bba0c91b'

// Compute ECRECOVER
await Verification.getRecover(sigHash, sigWJS) --> '0xD9995BAE12FEe327256FFec1e3184d492bD94C31'
await Verification.getRecover(sigHash, sigEJS) --> '0x5A8B991627bd17cdA2f2Cc1C5E07E8922E767F9B'
ethers.utils.verifyMessage(sigHash, sigWJS) --> '0x07e17feCCaD85Db39a4c722d05b5c9b968e7A3fb'
ethers.utils.verifyMessage(sigHash, sigEJS) --> '0xD9995BAE12FEe327256FFec1e3184d492bD94C31'
web3.eth.accounts.recover(sigHash, sigWJS, false) --> '0xD9995BAE12FEe327256FFec1e3184d492bD94C31'
web3.eth.accounts.recover(sigHash, sigEJS, false) --> '0x508bD95152655c71adCEcbA418F4c826310ec327'
discussion

Most helpful comment

Nice :) That did the trick.

All 2 comments

Keep in mind that hashMessage takes in either a string (UTF-8 message), or an array (e.g. Uint8Array) which is processed as binary data.

The string "0x648978d27edc284b1a72048fdeb2147d5292601d09ba43b3fb29ca0307777d9e" is 66 bytes long. What you probably want is the binary data of length 32, i.e.

let sigHashBytes = ethers.utils.arrayify(sigHash);
let sigEJS = await user.signMessage(sigHashBytes);
ethers.utils.verifyMessage(sigHashBytes, sigEJS);

Let me know if that helps. :)

Nice :) That did the trick.

Was this page helpful?
0 / 5 - 0 ratings