ecrecover in Solidity gibt Nulladresse zurück [Duplikat]

Ich brauche Hilfe bei der Überprüfung der Ethereum-Adresse. Ich folge dem Tutorial zum Signieren und Validieren der Ethereum-Adresse. GitHub-Code . Ich bin verwirrt über mein tatsächliches Ergebnis der Adresse, nachdem ich gelaufen bin, loginContractInstance.recoverAddr.call(addr, fixed_msg_sha, v_decimal, r,s, function(err, actual) {weil es null zurückgibt.

Hier ist mein Backend-Code unten,

// 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);
    }

});

Und mein intelligenter Vertrag,

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;
}

Hier ist das Ergebnis dieses Funktionsaufrufs in meiner Konsole:

Geben Sie hier die Bildbeschreibung ein

Kann jemand helfen, was ich vermisse?

BEARBEITEN

Ich habe die Funktion recoverAddr.call korrigiert, um die richtige Eingabe zu verwenden. Ich habe auch herausgefunden, dass mein fixed_msg_shaProblem ist, weil ich hinzugefügt 0xhabe const fixed_msg_sha = '0x' + web3.sha3(fixed_msg). Es wurde so gedruckt0x0xf348f6a3d221a5e7e851292474330ca6e6cf6ad54572ee114233ab9b9225ab4f

Jetzt hat sich das Problem dahingehend geändert, dass eine 0x-Adresse zurückgegeben wird.Geben Sie hier die Bildbeschreibung ein

Antworten (2)

Ihre Smart-Contract-Funktion:

function recoverAddr(bytes32 msgHash, uint8 v, bytes32 r, bytes32 s)

Ihr Backend-Code:

loginContractInstance.recoverAddr.call(addr, fixed_msg_sha, v_decimal, r,s, function(err, actual) {

addrDenken Sie nicht, dass Sie als ersten Parameter übergeben wollten ?

Ich bin mir nicht sicher, warum es sich nicht über "ungültige Anzahl von Argumenten für die Soliditätsfunktion" beschwert

Danke für die Korrektur meiner Unachtsamkeit. Aber das Problem bleibt bestehen, nachdem ich es korrigiert habe. Es gibt immer noch null zurück.

Ich f, Sie verwenden dies, um die Preimages zu rekonstruieren: \x19Ethereum Signed Message:\n30` Was im Medium-Post angegeben ist. Es ist falsch, dass die richtige Byte-Zeichenfolge lautet:

\x19Ethereum Signed Message:\n32

Ich habe mir das gleiche Beispiel wie Sie angesehen und war beim ersten Experimentieren mit der Signaturüberprüfung extrem festgefahren, da es falsch ist (vielleicht war es richtig, als der Medium-Beitrag geschrieben wurde, aber nicht mehr).

Ich habe einen Vertrag geschrieben, der Ecrecover und geth-signierte Nachrichten verwendet. Sie können sich die Signaturpräfix-Erklärung hier ansehen: https://github.com/postables/Postables-Payment-Channel/blob/7d2f91bb060f80b139cab72b5fdff79d116f6210/solidity/ChannelsV4. sol#L12 und beachten Sie, dass es nicht mit dem übereinstimmt, was der Autor des Medium-Beitrags angegeben hat.

Die eigentliche Signaturprüfung findet hier statt:

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

Meine persönliche Präferenz zum Signieren von Nachrichten ist die Verwendung von Python Web3 + einem lokalen Geth-Knoten, wie dieses Python-Skript zeigt:

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

In meinem Fall habe ich das Tutorial nicht befolgt, weil ich es verwende, const fixed_msg = \x19Ethereum Signed Message:\n${msg.length}${msg}da es einstellbarer ist.
Das ist der Fehler, dass Sie den Hash der Nachricht signieren, nicht die Nachricht. Der Hash ist immer 32 Bytes groß.