用ecrecover來驗簽名

在geth console,可以直接呼叫
personal.sign(message, account, [password])來簽名
personal.ecRecover(message, signature)來驗簽名,return簽名的人

而在這裡我想用contract的方式來做驗簽名

用geth console先簽個名

user = eth.accounts[0]
// hash the msg
sha3msg = web3.sha3(‘hello’)
sig = web3.eth.sign(user, sha3msg)
"""這邊是註解
r = signature[0:64]
s = signature[64:128]
v = signature[128:130]
v should be 27 or 28. If it isn’t, set v = v + 27
"""
r = sig.slice(0,66)
s = '0x' + sig.slice(66,130)
v = '0x' + sig.slice(130,132)
v = web3.toDecimal(v)

v值應為27 or 28,如果v = 0或1的話,需加上27

用contract裡的ecrecover來驗簽名
先部署一個verify的合約

pragma solidity ^0.4.0;
contract test {
function verify(bytes32 _message, uint8 _v, bytes32 _r, bytes32 _s) constant returns (address) {
bytes memory prefix = “\x19Ethereum Signed Message:\n32”;
bytes32 prefixedHash = sha3(prefix, _message);
address signer = ecrecover(prefixedHash, _v, _r, _s);
return signer;
}
}
在合約中 sha(‘123’)和sha(‘12’, ‘3’)是一樣的

這裡有加了一個prefix,我不是很清楚為什麼一定得加,而在go-ethereum的wiki/Management APIs/personal_sign中寫到

The sign method calculates an Ethereum specific signature with:
sign(keccack256("\x19Ethereum Signed Message:\n" + len(message) + message))).
By adding a prefix to the message makes the calculated signature recognisable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim.

最後在geth中去呼叫test.verify(msg, v, r, s, {from:user})就會得到signer的address.(順便把CW提醒我們要加from的參數記錄下來)