Ecrecover kann nicht in Solidität verwendet werden, um die zum Signieren einer Nachricht verwendete Adresse wiederherzustellen, sondern gibt einfach die Adresse 0x0 zurück

Ich mache folgendes in geth:

var msgHash = web3.sha3("hello")
var signature = eth.sign(eth.accounts[0], msgHash)
var r = signature.slice(0,64)
var s = "0x" +signature.slice(64,128)
var v = signature.slice(128,130)

r = signature.slice(0,64) "0x6d49c891d29b33c292232f690c9972e17e0dbead7d4fc446bb4ce5892f0e55" s = signature.slice(64,128) "a22c9f3c20a7f0bc90666d1d1c6f269658a0ccd56b1db1812671e23331d8ad2c" v = signature.slice(128,130) "52"

Ich rufe dann den folgenden Solidity-Code auf

function verify(bytes32 msgHash, uint8 v, bytes32 r, bytes32 s) public {
    bytes memory prefix = "\x19Ethereum Signed Message:\n32";
    bytes32 prefixedHash = keccak256(prefix, msgHash);
    a = ecrecover(prefixedHash, v, r, s);
}

Was Folgendes zurückgibt:0x0000000000000000000000000000000000000000

Völlig ratlos, habe ich mir folgende Threads angesehen, ohne Erfolg:

ecrecover von Geth und web3.eth.sign

Antworten (3)

Sie müssen das 0x entfernen, bevor Sie den Slice ausführen - es soll nur zeigen, dass die Zeichenfolge hex ist und nicht Teil des r-Werts.

Sie müssen das Präfix loswerden, 0xbevor Sie in Scheiben schneiden.

ethereumjs-utilhat eine sehr praktische Funktion fromRpcSig, man kann sie gerne verwenden

const eutil = require('ethereumjs-util')

const hash = web3.sha3('hello world')
const rpcSig = web3.eth.sign(web3.eth.coinbase, eutil.bufferToHex(hash))
const rsv = eutil.fromRpcSig(rpcSig)
// then call your ecrecover with 
// hash, eutil.bufferToHex(rsv.r), eutil.bufferToHex(rsv.s), rsv.v
Danke! Obwohl ich nicht sehr gut in Javascript bin, habe ich einen Blick in die Bibliothek geworfen und konnte eine passende Python-Version finden.

Sowohl Flygoing als auch Liberty waren insofern richtig, als ich das Präfix vor dem Slicen entfernen musste 0x, aber ich musste das Präfix nach dem Slice wieder hinzufügen, was mich ein wenig brauchte, um es herauszufinden. Ich konnte web3py verwenden, um das Slice automatisch voranzustellen und auszuführen, wodurch die richtige Adresse immer noch nicht wiederhergestellt werden konnte. Erst als ich das 0xPräfix wieder hinzugefügt habe rund ses funktioniert hat. Als Ergebnis konnte ich den folgenden web3py-Code erstellen:

decryptedPrivateKey = w3.eth.account.decrypt(encrypted, password)
attribDict = w3.eth.account.sign(message_text="testmessage", private_key=decryptedPrivateKey)
msgHash = Web3.toHex(attribDict['messageHash'])
v = attribDict['v']
r = attribDict['r']
s = attribDict['s']
r = Web3.toHex(r)
s = Web3.toHex(s)
vrs = (v,r,s)
contract.functions.testRecovery(msgHash,v,r,s).transact({'from': w3.eth.accounts[0], 'gasPrice': 91000000000})
print("v:\t",v,"\nr:\t",r,"\ns:\t",s,"\nmsgHsh:\t",msgHash)
recoveredAddress = w3.eth.account.recover(msgHash,vrs=vrs)

Die testRecoveryvon mir verwendete Solidity-Funktion:

function testRecovery(
    bytes32 _msgHash, 
    uint8 _v, 
    bytes32 _r,
    bytes32 _s)
    public
    returns (bool)
{
    returned = ecrecover(_msgHash, _v, _r, _s);
    if (returned == expected) {
        return true;
    } else {
        return false;
    }
}
Hier signieren Sie mit web3.eth.account.sign (msg, private_key), aber in Ihrer Frage haben Sie mit web3.eth.sign (msg, public_key) signiert. Ich denke, beide funktionieren auf unterschiedliche Weise. web3.eth.account.sign() stellt die Zeichenfolge „\x19Ethereum Signed Message:\n32“ voran, bevor die Nachricht signiert wird. Andererseits stellt web3.eth.account.sign() diese Zeichenfolge nicht voran. Während der Dekodierung denke ich, dass die Signatur web3.eth.sign() nicht funktioniert. Das ist bei mir gerade der Fall.