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:
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, 0x
bevor Sie in Scheiben schneiden.
ethereumjs-util
hat 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
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 0x
Präfix wieder hinzugefügt habe r
und s
es 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 testRecovery
von 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;
}
}
hextet