Estoy tratando de firmar una cadena usando web3.eth.sign() y luego obtener la clave pública con la que firmé de la firma. Para hacer esto, estoy usando ecrecover() de ethereumjs-utils, que devuelve un búfer. Cuando uso bufferToHex() en el búfer, da una cadena hexadecimal que es demasiado larga para ser una dirección: 130 caracteres, incluido '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)
Tomé la mayor parte del código de la respuesta al flujo de trabajo al firmar una cadena con clave privada, seguido de la verificación de firma con clave pública, pero tuve que convertir 'msg' en un búfer ya que ecrecover arrojó un error de tipo de lo contrario.
¿Qué debo hacer para convertir el búfer de ecrecover a una dirección?
ecrecover
devuelve la clave pública , debe convertirla en una dirección con pubToAddress
.
pub = ethJsUtil.ecrecover(msg, v, r, s);
addrBuf = ethJsUtil.pubToAddress(pub);
addr = ethJsUtil.bufferToHex(addrBuf);
Además, puede utilizar fromRpcSig
para obtenerv, r, s
sig = web3.eth.sign(myAccount,msg)
res = ethJsUtil.fromRpcSig(sig)
pub = ethJsUtil.ecrecover(msg, res.v, res.r, res.s);
Tenga en cuenta que web3.eth.sign
agrega un prefijo al mensaje antes de firmarlo (consulte la especificación JSON-RPC ).
Aquí se explica cómo agregarlo manualmente:
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);
Por otro lado, testrpc (al menos la versión 3.0.5) no agrega dicho prefijo.
Ejemplo node.js + sesión testrpc:
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);
v, r, s
recuperación, intente usar fromRpcSig
.Ejemplo node.js + ethereumjs-util otro método para validar la firma
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");
DappDev
José