ecrecover 在solidity 中返回空地址
我需要有關乙太坊地址驗證的幫助。我正在關注關於簽名和驗證乙太坊地址的教程。GitHub 程式碼。我對執行後地址的實際結果感到困惑,
loginContractInstance.recoverAddr.call(addr, fixed_msg_sha, v_decimal, r,s, function(err, actual) {
因為它返回 null。這是我下面的後端程式碼,
// Unlock account before the login attempt web3.personal.unlockAccount(req.body.address, req.body.password, 100, function(error, unlocked) { console.log(`>>>>> Login - User is unlocked: ${unlocked}`); if (unlocked) { // Signing/ Encryption const addr = req.body.address; const msg = req.body.password; const hex_msg = '0x' + toHex(msg); let signature = web3.eth.sign(addr, hex_msg); console.log(`address -----> ${addr}`); console.log(`msg ---------> ${msg}`); console.log(`hex(msg) ----> ${hex_msg}`); console.log(`sig ---------> ${signature}`); const r = signature.slice(0, 66) const s = '0x' + signature.slice(66, 130) const v = '0x' + signature.slice(130, 132) const v_decimal = web3.toDecimal(v); console.log(`r -----------> ${r}`); console.log(`s -----------> ${s}`); console.log(`v -----------> ${v}`); console.log(`vd ----------> ${v_decimal}`); // Validation/Decryption const fixed_msg = `\x19Ethereum Signed Message:\n${msg.length}${msg}` const fixed_msg_sha = '0x' + web3.sha3(fixed_msg) loginContractInstance.isSigned.call(addr, fixed_msg_sha, v_decimal, r, s, function (err, signed) { console.log(`>>>>> Login - Signature: ${signed}`); if (signed) { // Saving login attempt loginContractInstance.successfulLogin.sendTransaction(req.body.address, req.body.password, {from:'6ded1c5b448819a6cde4293e33fbe54583ef5c52', gas:200000}, function(err, transactionHash) { if (!err) { console.log(`>>>>> Login - login details (${addr}, ${msg}) successfully saved @ ${transactionHash}`); console.log(`>>>>> Login - Successfully login`); } else { console.log(`>>>>> Login - login transaction failed: ${err}`); } // set primary account to mine web3.eth.coinbase = req.body.address; console.log(`>>>>> Login - Current User: ${web3.eth.coinbase} is logged in`); var balanceWei = web3.eth.getBalance(req.body.address).toNumber(); var balance = web3.fromWei(balanceWei, 'ether'); res.json({ allowedLogin: true, address: req.body.address, balance: balance, token: generateToken(addr) }); }); } else { loginContractInstance.recoverAddr.call(fixed_msg_sha, v_decimal, r,s, function(err, actual) { console.log(`>>>>> Login - Failed login: Signature not matched:${addr} = ${actual}`); saveFailedLoginAttempts(loginContractInstance, req, res); }); } }); } else { console.log(`>>>>> Login - Failed login: User is locked`); saveFailedLoginAttempts(loginContractInstance, req, res); } });
還有我的智能合約,
contract Login { event LoginAttempt(address sender, string password); address private sender; string private password; function successfulLogin (address _sender, string _password) public { LoginAttempt(_sender, _password); sender = _sender; password = _password; } function failedLogin (address _sender, string _password) public { LoginAttempt(_sender, _password); } function recoverAddr(bytes32 msgHash, uint8 v, bytes32 r, bytes32 s) public pure returns (address) { return ecrecover(msgHash, v, r, s); } function isSigned(address _addr, bytes32 msgHash, uint8 v, bytes32 r, bytes32 s) public pure returns (bool) { return ecrecover(msgHash, v, r, s) == _addr; }
這是我控制台中該函式呼叫的結果,
誰能幫助我缺少什麼?
編輯
我已經更正了 recoverAddr.call 函式以使用正確的輸入。我也發現我
fixed_msg_sha
的問題是因為我添加0x
了const fixed_msg_sha = '0x' + web3.sha3(fixed_msg)
. 是這樣列印的0x0xf348f6a3d221a5e7e851292474330ca6e6cf6ad54572ee114233ab9b9225ab4f
你的智能合約功能:
function recoverAddr(bytes32 msgHash, uint8 v, bytes32 r, bytes32 s)
你的後端程式碼:
loginContractInstance.recoverAddr.call(addr, fixed_msg_sha, v_decimal, r,s, function(err, actual) {
不要認為您打算
addr
作為第一個參數傳遞?不知道為什麼它不抱怨“solidity 函式的參數數量無效”
我如果你用它來重建原像: `\x19Ethereum Signed Message:\n30``這是在媒體文章中給出的,正確的字節字元串是不正確的:
\x19Ethereum Signed Message:\n32
我查看了與您相同的範例,並且在第一次嘗試簽名驗證時非常卡住,因為它是不正確的(也許在編寫中型文章時它是正確的,但現在不是了。)
我有一份使用 ecrecover 和 geth 簽名消息的契約,您可以在此處查看簽名前綴聲明:https://github.com/postables/Postables-Payment-Channel/blob/7d2f91bb060f80b139cab72b5fdff79d116f6210/solidity/ChannelsV4。 sol#L12並註意它與中篇文章的作者給出的不符。
實際的簽名驗證在這裡進行:
我個人對消息簽名的偏好是使用 python web3 + 本地 geth 節點,如下 python 腳本所示:
https://github.com/postables/Postables-Payment-Channel/blob/develop/python/signer.py