Go-Ethereum

ecrecover 在solidity 中返回空地址

  • April 4, 2018

我需要有關乙太坊地址驗證的幫助。我正在關注關於簽名和驗證乙太坊地址的教程。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的問題是因為我添加0xconst fixed_msg_sha = '0x' + web3.sha3(fixed_msg). 是這樣列印的0x0xf348f6a3d221a5e7e851292474330ca6e6cf6ad54572ee114233ab9b9225ab4f

現在問題變成了返回一個 0x 地址, 在此處輸入圖像描述

你的智能合約功能:

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並註意它與中篇文章的作者給出的不符。

實際的簽名驗證在這裡進行:

https://github.com/postables/Postables-Payment-Channel/blob/7d2f91bb060f80b139cab72b5fdff79d116f6210/solidity/ChannelsV4.sol#L257

我個人對消息簽名的偏好是使用 python web3 + 本地 geth 節點,如下 python 腳本所示:

https://github.com/postables/Postables-Payment-Channel/blob/develop/python/signer.py

引用自:https://ethereum.stackexchange.com/questions/44597