La verificación de la firma de Ethereum no coincide

Lo que quiero lograr es firmar un mensaje y luego verificar la firma, ya sea verificada por la misma dirección o no.

Contrato para invocar el método ecrecover para verificar la dirección

contract MyAuth {      
    function verify( bytes32 hash, uint8 v, bytes32 r, bytes32 s) 
        constant returns(address returnAddress) {
        returnAddress = ecrecover(hash, v, r, s);
    }
}

Código de secuencias de comandos de Java

var cMyAuthAddress="0x09343c5EBB988315E117E1Cd6EE501AF02412cFB"; // Contract address

var cMyAuthABI="<ABI data>"; // Contract ABI
var cDeployed=web3.eth.contract(JSON.parse(cMyAuthABI)).at(cMyAuthAddress);

var msg = web3.sha3('This my test data');

console.log('Message Hash: '+ msg); // Generated message hash
console.log("Account Used to Sign: "+ web3.eth.accounts[0]);
var state=web3.personal.unlockAccount(web3.eth.accounts[0], '<account password>', 1000); // Unlocking the account to perform the operation
console.log('Account State: '+ state);

var signature = web3.eth.sign(web3.eth.accounts[0], msg); // Signing the messge

console.log('Signature: '+ signature);

var r = signature.slice(0, 66)
var s = '0x' + signature.slice(66, 130)
var v = '0x' + signature.slice(130, 132)
v = web3.toDecimal(v);

console.log("V: "+ v);
console.log("R: "+ r);
console.log("S: "+ s);

if(v<27 || v>28){
    v+=27;
    console.log("Updated V: "+ v);
}

var finalAddress=cDeployed.verify.call(msg,v,r,s)

console.log("Final Address: "+ finalAddress);

Producción

Message Hash: 0x1c6f4ab842fb95857783a0177eafb0133b3a626c89877a8bf4e2d07987aa1422
Account Used to Sign: 0x890bd380e472df5b8bab22075c6a5d4f0b84415c
Account State: true
Signature: 0xb8b01f46f147bd5e8f84343719ca7492164f80af5f60370c433e2e096ae52fec76d2bbe0e454b2a07e4100e8463d98286ec6e849cbcf6e24f66f7d579fc8654f1c
V: 28
R: 0xb8b01f46f147bd5e8f84343719ca7492164f80af5f60370c433e2e096ae52fec
S: 0x76d2bbe0e454b2a07e4100e8463d98286ec6e849cbcf6e24f66f7d579fc8654f
Decimal V: 28
Final Address: 0x0609b9fae476d8b844716e3a0a6a3b5b7a5a2cdf

Puede ver claramente que la dirección final enumerada no coincide con la utilizada para firmar el mensaje.

Nota: estoy intentando esto en mi cadena de bloques privada.

Pregunta : ¿Qué paso debe corregirse para lograr el resultado deseado (es decir, la dirección final debe coincidir con la dirección de la cuenta utilizada para iniciar sesión en este caso, que es 0x890bd380e472df5b8bab22075c6a5d4f0b84415c )?

Intenté usar ethereumjs-util con el valor de firma generado por baove pero obtuve el mismo resultado.

  var ethUtils = require('ethereumjs-util'); 
  let tSig = ethUtils.fromRpcSig(signature);
  let pubKey = ethUtils.ecrecover(
    ethUtils.sha3("This my test data"),
    tSig.v,
    tSig.r,
    tSig.s);
  let foundAddr = '0x' + ethUtils.pubToAddress(pubKey).toString('hex');
  console.log("Final Address 2: "+ finalAddress);

La salida es la dirección final 2: 0x0609b9fae476d8b844716e3a0a6a3b5b7a5a2cdf "(es decir, la misma dirección)

Respuestas (1)

Debe prefijar el mensaje con la cadena "\x19Ethereum Signed Message:\n" y la longitud del mensaje

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

Y luego use la cadena prefijada en ecrecover.

código tomado de la respuesta aquí https://ethereum.stackexchange.com/a/12684/

Muchas gracias por compartir los detalles al respecto. Ahora puedo descifrar la dirección con la que se generó la firma.