Web3js Signature – web3.eth.sign Not Returning Valid Signature

ecrecoverethereumjsgo-ethereumparitysignature

EDIT: Problem Solved; working example of login below

I use the sha3 of a message I want to sign with eth.sign
m = web3.sha3("Please work.")

I then runeth.sign(eth.coinbase, m)

And it returns me: 0x1c28d6720234343026c24718728cf0c251b0d09c87c32a6e380396a3360065290d0e7ec99a48e547e36645cecc11fd8d09742955c3d16c32eb75d9b24dd158d754

Theoretically, I would be able to derive the validity of the signature from this.

r = 0x1c28d6720234343026c24718728cf0c251b0d09c87c32a6e380396a336006529

s = 0x0d0e7ec99a48e547e36645cecc11fd8d09742955c3d16c32eb75d9b24dd158d7

v = 54?! ( I was under the impression this would be a 0 or 1. For ecrecover I tried 27 and 28 )

Now I plug these into ecrecover(m, v, r, s) and I get…

With 27: 0x8c6c953abf2957f7fec4c689f8fe2ff09b81b245

With 28: 0xb8feaa9b9bfd7f10caefdc6d7baa1f74c37cedef

What in the world is going on? I'm trying to implement a login for my application using web3 and this is a major roadblock. I'm hoping you geniuses can correct me where I'm wrong.

Thanks.

Best Answer

I came across the answer myself, See working code below. I was following this guide which I would not recommend!.

I was also using parity in geth mode to sign the data, which I also would not recommend. Switching to plain old geth RPC gave me more sane results.

That being said, beware of v!. There is a bug between implementations of geth which will return either 00/01 or 1b/1c for v. I solved my problem by using ethereumjs-util's fromRpcSig method, which accounts for the bug. If the following doesn't work try importing web3 and using its sha3 method with ethUtils toBuffer.

Here's a complete snippet of code client side and server side which implement login:

CLIENT

function login() {
  let data = web3.sha3('hello world');
  web3.eth.sign(web3.eth.defaultAccount, data, (err, result) => {
    if (!err) {
      axios.post(url + '/login', {
        addr: web3.eth.defaultAccount,
        sig: result
      }).then((res) => {
        console.log(res);
      });

    }
  });
}

SERVER

var ethUtils = require('ethereumjs-util');

let addr = req.body.addr;
let sig = req.body.sig;

let signature = ethUtils.fromRpcSig(sig);

let data = 'hello world';

let pubKey = ethUtils.ecrecover(
  ethUtils.sha3(data),
  signature.v,
  signature.r,
  signature.s);

let foundAddr = '0x' + ethUtils.pubToAddress(pubKey).toString('hex');

if (foundAddr === addr) {
  // Hooray! The user's signature proves they are who they say they are!
} else {
  // Not authenticated successfully
}
Related Topic