材料
- web3.js 0.2x.x 文档 https://github.com/ethereum/wiki/wiki/JavaScript-API
- web3.js 1.0.0 文档 https://web3js.readthedocs.io/en/1.0/web3-eth-accounts.html#recover
思路
- 生成一个随机字符串
- 让用户用私钥加密这个字符串
- 平台使用公钥解密这个字符串,核对和步骤 1 生成的字符串一致, 则通过, 不一致则认为失败
步骤
我需要验证一个用户对这个地址的所有权。 思路是 使用 web3.eth.sign 函数, 让用户用私钥签名一段字符串hello world, 然后用公钥对字符串进行解密, 如果解密后的字符串是hello world, 则认为用户对该地址有所有权。
签名
我使用 web3.eth.sign 函数, 对 hello world 进行签名, 得到一个 字符串
web3.eth.sign("0xec7a2d8FcBc0BAc118c23F9faA122ff833fe048a",web3.sha3("hello world"),function(error,result){console.log(result);});
0xd7d9614315e4b5c35d1ac26f41b2d9c6a217fb4fabb5aa343938324351b6c0ea5fbc60562a56df03e9da71a143fd753832c5ead2d8ad1aaa4ee6974f3f05cb491b
注意点
- web3.eth.sign 接受的第二个参数, 需要用 web3.sha3 进行 hash 一下。
解密
之后,我要去验证这个字符串可以用公钥解密, 我发现 web3.js 0.2x.x 没有提供这个接口。在 1.0.0 的文档中找到了 web3.eth.accounts.recover 方法。 然而 metamask 并不支持
https://web3js.readthedocs.io/en/1.0/web3-eth-accounts.html#recover
其他方法
找到的其他方法是
https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/index.md#ecrecover
通过 esrecover 方法,
通过 签名后的字符串,算出公钥地址。 如果一致, 则认为成功。
ecdsa 接受4个参数, 分别是 msgHash 和 v,r,s , 其中 msgHash 就是你加密的字符串, v,r,s 可以通过 加密后的字符串计算出来。
如何计算 v,r,s 参考 这里
https://ethereum.stackexchange.com/questions/2660/how-can-i-verify-a-signature-with-the-web3-javascript-api