ecrecover
returns public key, you need to convert it to address with pubToAddress
.
pub = ethJsUtil.ecrecover(msg, v, r, s);
addrBuf = ethJsUtil.pubToAddress(pub);
addr = ethJsUtil.bufferToHex(addrBuf);
Also, you can use fromRpcSig
to get v, r, s
sig = web3.eth.sign(myAccount,msg)
res = ethJsUtil.fromRpcSig(sig)
pub = ethJsUtil.ecrecover(msg, res.v, res.r, res.s);
Please note that web3.eth.sign
adds prefix to the message before signing it (see JSON-RPC spec).
Here is how to add it manually:
const util = require('ethereumjs-util')
const msg = new Buffer('hello');
const sig = web3.eth.sign(web3.eth.accounts[0], '0x' + msg.toString('hex'));
const res = util.fromRpcSig(sig);
const prefix = new Buffer("\x19Ethereum Signed Message:\n");
const prefixedMsg = util.sha3(
Buffer.concat([prefix, new Buffer(String(msg.length)), msg])
);
const pubKey = util.ecrecover(prefixedMsg, res.v, res.r, res.s);
const addrBuf = util.pubToAddress(pubKey);
const addr = util.bufferToHex(addrBuf);
console.log(web3.eth.accounts[0], addr);
On the other hand, testrpc (at least version 3.0.5) does not add such prefix.
Example node.js + testrpc session:
const util = require('ethereumjs-util')
const msg = web3.sha3('hello!');
const sig = web3.eth.sign(web3.eth.accounts[0], msg);
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(web3.eth.accounts[0], addr);
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);
}
Best Answer
Old issue, but this worked for me. I'm using web3@0.20.3.
1. With personal_sign (recommended)
Client side:
Server side:
2. With eth_sign
Client side:
Server side: