I have had a similar issue and discovered that the eth_sign
RPC call does not sign the passed message, but a transformation of it.
Quote from https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
The sign method calculates an Ethereum specific signature with: sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)))
.
(Where len(message)
is the ASCII decimal representation of the length)
One option is to pass keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)
instead of message
as first argument to ecrecover()
. Another is to use a more low-level version of eth_sign
.
- N/A, in that you don't need to unlock an account at all.
- Yes, see below.
The following uses Web3.js version 1.0.0-beta which is now the default installed by npm. Note that no node is attached.
> var Web3 = require('web3');
> var web3 = new Web3();
> web3.version
'1.0.0-beta.10'
The second parameter in the below is the private key:
> web3.eth.accounts.sign("Hello, world!", '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef')
{ message: 'Hello, world!',
messageHash: '0xb453bd4e271eed985cbab8231da609c4ce0a9cf1f763b6c1594e76315510e0f1',
v: '0x1b',
r: '0x3bc843a917d6c19c487c1d0c660cdd61389ce2a7651ee3171bcc212ffddca164',
s: '0x193f1f2e06f7ed8f9fbf2254232d99848a8102b552032b68a5507b4d81492f0f',
signature: '0x3bc843a917d6c19c487c1d0c660cdd61389ce2a7651ee3171bcc212ffddca164193f1f2e06f7ed8f9fbf2254232d99848a8102b552032b68a5507b4d81492f0f1b' }
And the signature checks out, too (the recovered account is the same as the account generated from the private key directly):
> web3.eth.accounts.recover('0xb453bd4e271eed985cbab8231da609c4ce0a9cf1f763b6c1594e76315510e0f1', '0x1b', '0x3bc843a917d6c19c487c1d0c660cdd61389ce2a7651ee3171bcc212ffddca164', '0x193f1f2e06f7ed8f9fbf2254232d99848a8102b552032b68a5507b4d81492f0f')
'0xFCAd0B19bB29D4674531d6f115237E16AfCE377c'
>
> web3.eth.accounts.privateKeyToAccount('0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef');
{ address: '0xFCAd0B19bB29D4674531d6f115237E16AfCE377c',
privateKey: '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
...}
Best Answer
web3
does not support this feature yet, but it might be coming with web3 1.0.In the meantime you can use ethereumjs-utils ecrecover feature. Note that this function expects
v
to be in {27, 28}, and since your signature comes from geth, (since it doesn't return signatures in the canonical format yet) you will have to add27
to yourv
.Given a signature
sgn
of a the hashed messagemsg
, you can use the ethereumjs-util library like this:To do the verification in a solidity contract, check out this answer.