Abrufen einer Adresse von ethereumjs-utils ecrecover

Ich versuche, eine Zeichenfolge mit web3.eth.sign() zu signieren und dann den öffentlichen Schlüssel, mit dem ich signiert habe, aus der Signatur abzurufen. Dazu verwende ich ecrecover() von ethereumjs-utils, das einen Puffer zurückgibt. Wenn ich bufferToHex() für den Puffer verwende, gibt es eine Hex-Zeichenfolge, die viel zu lang ist, um eine Adresse zu sein - 130 Zeichen einschließlich '0x'

web3.personal.unlockAccount(myAccount,pass)
msg = web3.sha3(aString)
sig = web3.eth.sign(myAccount,msg)
r = sig.slice(0, 66)
s = '0x' + sig.slice(66, 130)
v = '0x' + sig.slice(130, 132)
v = web3.toDecimal(v)
msg = ethJsUtil.toBuffer(msg)
addr = ethJsUtil.ecrecover(msg,v,r,s)
addr = ethJsUtil.bufferToHex(addr)

Ich habe den größten Teil des Codes aus der Antwort auf den Workflow zum Signieren einer Zeichenfolge mit privatem Schlüssel genommen, gefolgt von der Signaturüberprüfung mit öffentlichem Schlüssel , musste aber „msg“ in einen Puffer konvertieren, da ecrecover andernfalls einen Typfehler auslöste.

Was muss ich tun, um den Puffer von ecrecover in eine Adresse umzuwandeln?

Auf welchem ​​OS bist du? hast du auch Meteor benutzt?
Ich verwende macOS Sierra und ja, dies verwendet Meteor

Antworten (2)

ecrecovergibt den öffentlichen Schlüssel zurück , Sie müssen ihn mit in eine Adresse umwandeln pubToAddress.

pub     = ethJsUtil.ecrecover(msg, v, r, s);
addrBuf = ethJsUtil.pubToAddress(pub);
addr    = ethJsUtil.bufferToHex(addrBuf);

Sie können auch verwenden fromRpcSig, um zu bekommenv, r, s

sig = web3.eth.sign(myAccount,msg)
res = ethJsUtil.fromRpcSig(sig)
pub = ethJsUtil.ecrecover(msg, res.v, res.r, res.s);

Bitte beachten Sie, dass web3.eth.signder Nachricht vor dem Signieren ein Präfix hinzugefügt wird (siehe JSON-RPC-Spezifikation ).

So fügen Sie es manuell hinzu:

const util = require('ethereumjs-util')

const msg = new Buffer('hello');
const sig = web3.eth.sign(web3.eth.accounts[0], '0x' + msg.toString('hex'));
const res = util.fromRpcSig(sig);

const prefix = new Buffer("\x19Ethereum Signed Message:\n");
const prefixedMsg = util.sha3(
  Buffer.concat([prefix, new Buffer(String(msg.length)), msg])
);

const pubKey  = util.ecrecover(prefixedMsg, res.v, res.r, res.s);
const addrBuf = util.pubToAddress(pubKey);
const addr    = util.bufferToHex(addrBuf);

console.log(web3.eth.accounts[0],  addr);

Auf der anderen Seite fügt testrpc (mindestens Version 3.0.5) kein solches Präfix hinzu.

Beispiel node.js + testrpc-Sitzung:

const util = require('ethereumjs-util')

const msg = web3.sha3('hello!');
const sig = web3.eth.sign(web3.eth.accounts[0], msg);
const {v, r, s} = util.fromRpcSig(sig);

const pubKey  = util.ecrecover(util.toBuffer(msg), v, r, s);
const addrBuf = util.pubToAddress(pubKey);
const addr    = util.bufferToHex(addrBuf);

console.log(web3.eth.accounts[0], addr);
Vielen Dank für die Beantwortung der PubToAddress ist definitiv das, wonach ich gesucht habe, aber sie gibt nicht dieselbe Adresse an wie die, mit der ich unterschrieben habe. Haben Sie eine Idee, woran das liegen könnte, oder soll ich diese Antwort als richtig markieren und eine neue Frage stellen?
Alles sollte in Ordnung sein. Ich habe meine Antwort mit einer Beispielsitzung aktualisiert. Es könnte ein Problem mit der v, r, sWiederherstellung geben, versuchen Sie es mit fromRpcSig.
Ich kopiere Ihren Demo-Code und erhalte immer noch andere Adressen, wenn ich ihn verwende.
Ich kann nicht sehen, warum dies einen Unterschied machen würde, aber ich musste die Zeile var web3 = new Web3(new Web3.providers.HttpProvider(" localhost:8545" )) anstelle Ihrer Zeilen 2-4 verwenden, da es die nicht finden konnte Modul
Welche Versionen von web3.js und ethereumjs-util verwenden Sie? Übrigens, ich denke, das verdient jetzt eine separate Frage.

Beispiel node.js + ethereumjs-util andere Methode zur Validierung der Signatur

const ethUtil = require("ethereumjs-util");

const inSignature = "0x...."; //user signed message
const message = "hello!";
const msgHex = ethUtil.bufferToHex(Buffer.from(message));
const msgBuffer = ethUtil.toBuffer(msgHex);
const msgHash = ethUtil.hashPersonalMessage(msgBuffer);

const signature = ethUtil.toBuffer(inSignature);

const sigParams = ethUtil.fromRpcSig(signature);
const publicKey = ethUtil.ecrecover(
            msgHash,
            sigParams.v,
            sigParams.r,
            sigParams.s
);

const sender = ethUtil.publicToAddress(publicKey);
const addr = ethUtil.bufferToHex(sender);

//now compare addr with user wallet address
if("0x<userWaller>" === addr) console.log("valid");