Nachricht mit Metamask signieren und mit ethereumjs-utils verifizieren

Kundenseite:

web3.eth.sign(address, hash); // generates signature

Serverseitig:

const ethutils = require('ethereumjs-util');

const extractAddress = function(signature, hash){ //signature and hash from the client side
  const o = ethutils.fromRpcSig(signature);
  const hashBuffer = ethutils.toBuffer(hash);
  const publicKeyBuffer = ethutils.ecrecover(hashBuffer, o.v, o.r, o.s);
  const publicKeyHex = ethutils.bufferToHex(publicKeyBuffer);
  const addressBuffer = ethutils.pubToAddress(publicKeyHex);
  const addressHex = ethutils.bufferToHex(addressBuffer);
  return addressHex;
}

Adressen stimmen nicht überein. Der Code funktionierte vorher (vor ein paar Monaten).

Relevante Diskussionen https://github.com/ethereumjs/ethereumjs-util/pull/67

Antworten (1)

Altes Problem, aber das hat bei mir funktioniert. Ich verwende web3@0.20.3.

1. Mit personal_sign ( empfohlen )

Kundenseite:

web3.personal.sign(web3.fromUtf8("dinosaur"), web3.eth.coinbase, console.log);

Serverseitig:

const msg = 'dinosaur';

const msgBuffer = ethereumJsUtil.toBuffer(msg);
const msgHash = ethereumJsUtil.hashPersonalMessage(msgBuffer);
const signatureBuffer = ethereumJsUtil.toBuffer(signature);
const signatureParams = ethereumJsUtil.fromRpcSig(signatureBuffer);
const publicKey = ethereumJsUtil.ecrecover(
  msgHash,
  signatureParams.v,
  signatureParams.r,
  signatureParams.s
);
const addressBuffer = ethereumJsUtil.publicToAddress(publicKey);
const address = ethereumJsUtil.bufferToHex(addressBuffer);

console.log(address); // Prints my initial web3.eth.coinbase

2. Mit eth_sign

Kundenseite:

web3.eth.sign(web3.eth.coinbase, web3.sha3("dinosaur"), console.log);

Serverseitig:

const msg = 'dinosaur';

const msgHash = ethereumJsUtil.sha3(msg);
// The rest is the same as above
const signatureBuffer = ethereumJsUtil.toBuffer(signature);
const signatureParams = ethereumJsUtil.fromRpcSig(signatureBuffer);
const publicKey = ethereumJsUtil.ecrecover(
  msgHash,
  signatureParams.v,
  signatureParams.r,
  signatureParams.s
);
const addressBuffer = ethereumJsUtil.publicToAddress(publicKey);
const address = ethereumJsUtil.bufferToHex(addressBuffer);

console.log(address); // Prints my initial web3.eth.coinbase
Ich wollte schon aufgeben und dann habe ich diesen Code ausprobiert. Lief wie am Schnürchen.
Darauf sollte überall verwiesen werden. Dies ist die beste Antwort auf diese Frage. Zwei Vorgehensweisen, zwei funktionierende Beispiele. Für zukünftige Benutzer: Jetzt heißt sha3 auf ethereumjs-util keccak256 und toBuffer funktioniert nicht mit Strings, also verwenden Sie Buffer.from()