I know this question has been asked and answered, but while trying to get everything to work, I've come across some problems. This is what I'm trying to do:
1. take a target string 'Schoolbus'
2. use JSON with geth to eth_sign it
3. obtain v,r,s of signature
4. attempt to verify with a solidity contract, need the hash of 'Schoolbus'
So here's what I got. First of all, we can't all use the same private key, so if someone can verify my work and get a gist of my problem, that would be great.
Pretending that my priv key is '0xd1ade25ccd3d550a7eb532ac759cac7be09c2719', to sign 'Schoolbus', I use
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sign","params":["0xd1ade25ccd3d550a7eb532ac759cac7be09c2719", "Schoolbus"],"id":1}'
Where I get the result
0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601
I'm using (I might be wrong here)
v=2a
r=c19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407
s=466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601
Then I whipped up my contract, which is a variation of an answer in a related thread:
contract Auth {
function verify( bytes32 hash, uint8 v, bytes32 r, bytes32 s) constant returns(address retAddr) {
retAddr= ecrecover(hash, v, r, s);
}
}
Because I never got the hash of 'Schoolbus', I tried a couple of things in web3.js (the UTF8 one confused me, I was expecting that {encoding:'hex'} version to be the correct one):
console.log('1 '+ web3.sha3(web3.toHex('Schoolbus'))); //05ab39621b81764697fcfb6ae4fcf6b023cd644721c67c13a49fbd769c75671c
console.log('2 '+ web3.sha3(web3.toHex('Schoolbus'),{encoding:'hex'}));//d030d9a04df643f62a1502b017f51c41a659268091abbd20e2de97b935724d7c
console.log('3 '+ web3.sha3('Schoolbus'));//d030d9a04df643f62a1502b017f51c41a659268091abbd20e2de97b935724d7c
console.log('4 '+ web3.sha3( unescape(encodeURIComponent('Schoolbus')) ) ); //to UTF8 //d030d9a04df643f62a1502b017f51c41a659268091abbd20e2de97b935724d7c
console.log('5 '+ web3.sha3( unescape(encodeURIComponent('Schoolbus')), {encoding:'hex'} ) ); //to UTF8 //8f1cbe7efcf383ffeb1aeaf1e826c778a087153344cbeba144fbe967ad3ab11a
I ended up using this, but don't know why:
0xd030d9a04df643f62a1502b017f51c41a659268091abbd20e2de97b935724d7c
Then I called the contract:
var contDep=web3.eth.contract( [abi def] ).at( contractAddress);
console.log(
contDep.verify('d030d9a04df643f62a1502b017f51c41a659268091abbd20e2de97b935724d7c', 2a,'c19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407', '466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601')
);
Here's my problem. I keep getting this weird address back. It starts with 0x, it's 20 bytes, but it doesn't have [a-f] in it:
0x3433663632613135303262303137663531633431
If I swapped r and s, I get almost the same result back.
I was wondering if someone can verify my experience, or point out what I was doing wrong. I feel like a crazy person here.
Thanks for all your help.
Best Answer
I was having the same problem earlier, so I am going to give an extensive answer to how this works. I assume you are using geth as a client. There is an open issue where the geth client returns
v
in the wrong format, so let's keep in mind that if we get av
that is0
or1
we should add27
to it. If you are running node and have connected web3 to your favorite client:In my case, the signature is:
The string represents
r
,s
, andv
respectively in that order. To feed it to your Auth contract however, you need to convertv
to anuint8
and add make sure to have the hex prefix0x
everywhere:Remember that
v
should be27
or28
! If it isn't, setv = v + 27
. You can now call your verify function like:and you can check that
addr
has the same value asweb3.eth.accounts[0]
.