6

Client side:

web3.eth.sign(address, hash); // generates signature

Server side:

const ethutils = require('ethereumjs-util');

const extractAddress = function(signature, hash){ //signature and hash from the client side
  const o = ethutils.fromRpcSig(signature);
  const hashBuffer = ethutils.toBuffer(hash);
  const publicKeyBuffer = ethutils.ecrecover(hashBuffer, o.v, o.r, o.s);
  const publicKeyHex = ethutils.bufferToHex(publicKeyBuffer);
  const addressBuffer = ethutils.pubToAddress(publicKeyHex);
  const addressHex = ethutils.bufferToHex(addressBuffer);
  return addressHex;
}

Addresses don't match. The code worked before (a couple of months ago).

Relevant discussions https://github.com/ethereumjs/ethereumjs-util/pull/67

9

Old issue, but this worked for me. I'm using web3@0.20.3.

1. With personal_sign (recommended)

Client side:

web3.personal.sign(web3.fromUtf8("dinosaur"), web3.eth.coinbase, console.log);

Server side:

const msg = 'dinosaur';

const msgBuffer = ethereumJsUtil.toBuffer(msg);
const msgHash = ethereumJsUtil.hashPersonalMessage(msgBuffer);
const signatureBuffer = ethereumJsUtil.toBuffer(signature);
const signatureParams = ethereumJsUtil.fromRpcSig(signatureBuffer);
const publicKey = ethereumJsUtil.ecrecover(
  msgHash,
  signatureParams.v,
  signatureParams.r,
  signatureParams.s
);
const addressBuffer = ethereumJsUtil.publicToAddress(publicKey);
const address = ethereumJsUtil.bufferToHex(addressBuffer);

console.log(address); // Prints my initial web3.eth.coinbase

2. With eth_sign

Client side:

web3.eth.sign(web3.eth.coinbase, web3.sha3("dinosaur"), console.log);

Server side:

const msg = 'dinosaur';

const msgHash = ethereumJsUtil.sha3(msg);
// The rest is the same as above
const signatureBuffer = ethereumJsUtil.toBuffer(signature);
const signatureParams = ethereumJsUtil.fromRpcSig(signatureBuffer);
const publicKey = ethereumJsUtil.ecrecover(
  msgHash,
  signatureParams.v,
  signatureParams.r,
  signatureParams.s
);
const addressBuffer = ethereumJsUtil.publicToAddress(publicKey);
const address = ethereumJsUtil.bufferToHex(addressBuffer);

console.log(address); // Prints my initial web3.eth.coinbase
2
  • I was about to give up and then I tried this piece of code. Worked like a charm. – atul Feb 4 '20 at 16:34
  • This should be referenced everywhere. This is the best answer to this question. Two ways of doing, two examples working. For futur users: now sha3 on ethereumjs-util is called keccak256 and toBuffer doesn't work on strings so use Buffer.from() – dievardump Jan 10 at 19:47

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.