5

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);
1
  • It's hard to debug your code when you haven't shared it.
    – user19510
    Apr 17, 2019 at 22:05

3 Answers 3

4

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);

}
2
  • I get this: Error: This method only supports Buffer but input was: Ethereum Signed Message. My Signature was done in frontend: web3.eth.personal.sign("Hello world", account[0], "test password!") | edit: maybe I need to do this in my frontend as well: nonce = "\x19Ethereum Signed Message:\n" + nonce.length + nonce; nonce = util.keccak(nonce); before I let the user sign the nonce.
    – Suisse
    Apr 5, 2021 at 17:08
  • so I did this: nonce = util.keccak(Buffer.from(nonce)); - no error, but I get a diffrent addr than the user who signed! Do I need to do something special in the frontend instead of: web3.eth.personal.sign(nonce, from[0], "test password!")
    – Suisse
    Apr 5, 2021 at 17:36
3

Did you try web3's web3.eth.personal.ecRecover?

For example, if you sign via

web3.eth.personal.sign("Hello world", "0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe", "test password!")
.then(console.log);

> "0x30755ed65396facf86c53e6217c52b4daebe72aa4941d89635409de4c9c7f9466d4e9aaec7977f05e923889b33c0d0dd27d7226b6e6f56ce737465c5cfd04be400"

You "recover" via...

web3.eth.personal.ecRecover("Hello world", "0x30755ed65396facf86c53e6217c52b4daebe72aa4941d89635409de4c9c7f9466d4e9aaec7977f05e923889b33c0d0dd27d7226b6e6f56ce737465c5cfd04be400").then(console.log);

> "0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe"

3
  • Sure I tried "web3.eth.personal.ecRecover", but it gives me error: "Cannot read property 'ecRecover' of undefined". Then I tried web3.personal.ecRecover, but this method produces error: "The method personal_ecRecover does not exist/is not available". So to me, it looks like the personal.ecRecover method works only in the browser, client-side, but not inside nodejs server-side. But after many hours I found a solution. Apr 18, 2019 at 12:18
  • 1
    Interesting. The personal interactions are typically limited to a client-side solution (the personal is also used for creating accounts, signing transactions, etc. and is dangerous to have that happening on an open, server node.) I wonder why this is personal though. Regardless, can you please post an answer to your question as a new answer to help people who may have similar issues in the future?
    – tayvano
    Apr 18, 2019 at 18:29
  • Do I understand this right: with sig() we get a signature based on a pre defined nonce ("Hello world") and afterwards, without having a private key, we can find out that the signature is really from the account we assume it should be? And what is the third argument of sing() the password?
    – Suisse
    Apr 5, 2021 at 15:34
3

Aug 2021

I achieve this by installing the npm package called eth-sig-util.

Here is my code:

const ethSigUtil = require("eth-sig-util");

function checkSignature(nonce, signature) {
    const msgParams = {
        data: nonce,
        sig: signature
    };
    return ethSigUtil.recoverPersonalSignature(msgParams);
}

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.