[Ethereum] How to recover the address from message and signature generated with web3.personal.sign

ethereumjsnodejsweb3js

Is there any way to do that? To recover address in nodejs server-side from signature and message after it was signed with web3.personal.sign client-side?
I tried this: https://ethereum.stackexchange.com/a/12580/42452 with ethereumjs-util; I tried recoverTypedSignature() from eth-sig-util but in both cases recovered addresses didn't match signing addresses.

Here is the client-side code:

function authorize() {
  web3.eth.getAccounts(function (err, account) {
    let nonce = "123ABC";
    web3.personal.sign(nonce, account[0], function (err, signature) {
      //send to nodejs server
      $.post("http://localhost:8087", {signature: signature, nonce: nonce, address: account[0]}, function (data) {
        console.log(data);
      });
    })
  })
}

and server-side:

app.post('/', cors(corsOptions), function(req, res){
const msg = web3.sha3(nonce);
const sig = signature;
const {v, r, s} = util.fromRpcSig(sig);

const pubKey  = util.ecrecover(util.toBuffer(msg), v, r, s);
const addrBuf = util.pubToAddress(pubKey);
const addr    = util.bufferToHex(addrBuf);

console.log(addr);
});
app.listen(8087);

Best Answer

So, after many hours, I found a solution, that works. To make it works I used method from ethereumjs-util - ecrecover. I had to add some prefixed message to signed nonce. Code looks like this:

function checkSignature(nonce, signature, res) {

  nonce = "\x19Ethereum Signed Message:\n" + nonce.length + nonce;
  nonce = util.keccak(nonce);
  const sig = signature;
  const {v, r, s} = util.fromRpcSig(sig);
  const pubKey  = util.ecrecover(util.toBuffer(nonce), v, r, s);
  const addrBuf = util.pubToAddress(pubKey);
  const addr    = util.bufferToHex(addrBuf);
  console.log(addr);

}
Related Topic