Necesito ayuda con la verificación de la dirección de Ethereum. Estoy siguiendo el tutorial sobre cómo firmar y validar la dirección de Ethereum. Código GitHub . Estoy confundido por mi resultado real de la dirección después de ejecutar loginContractInstance.recoverAddr.call(addr, fixed_msg_sha, v_decimal, r,s, function(err, actual) {
porque devuelve nulo.
Aquí está mi código backend a continuación,
// Unlock account before the login attempt
web3.personal.unlockAccount(req.body.address, req.body.password, 100, function(error, unlocked) {
console.log(`>>>>> Login - User is unlocked: ${unlocked}`);
if (unlocked) {
// Signing/ Encryption
const addr = req.body.address;
const msg = req.body.password;
const hex_msg = '0x' + toHex(msg);
let signature = web3.eth.sign(addr, hex_msg);
console.log(`address -----> ${addr}`);
console.log(`msg ---------> ${msg}`);
console.log(`hex(msg) ----> ${hex_msg}`);
console.log(`sig ---------> ${signature}`);
const r = signature.slice(0, 66)
const s = '0x' + signature.slice(66, 130)
const v = '0x' + signature.slice(130, 132)
const v_decimal = web3.toDecimal(v);
console.log(`r -----------> ${r}`);
console.log(`s -----------> ${s}`);
console.log(`v -----------> ${v}`);
console.log(`vd ----------> ${v_decimal}`);
// Validation/Decryption
const fixed_msg = `\x19Ethereum Signed Message:\n${msg.length}${msg}`
const fixed_msg_sha = '0x' + web3.sha3(fixed_msg)
loginContractInstance.isSigned.call(addr, fixed_msg_sha, v_decimal, r, s, function (err, signed) {
console.log(`>>>>> Login - Signature: ${signed}`);
if (signed) {
// Saving login attempt
loginContractInstance.successfulLogin.sendTransaction(req.body.address, req.body.password,
{from:'6ded1c5b448819a6cde4293e33fbe54583ef5c52', gas:200000},
function(err, transactionHash) {
if (!err) {
console.log(`>>>>> Login - login details (${addr}, ${msg}) successfully saved @ ${transactionHash}`);
console.log(`>>>>> Login - Successfully login`);
} else {
console.log(`>>>>> Login - login transaction failed: ${err}`);
}
// set primary account to mine
web3.eth.coinbase = req.body.address;
console.log(`>>>>> Login - Current User: ${web3.eth.coinbase} is logged in`);
var balanceWei = web3.eth.getBalance(req.body.address).toNumber();
var balance = web3.fromWei(balanceWei, 'ether');
res.json({
allowedLogin: true,
address: req.body.address,
balance: balance,
token: generateToken(addr)
});
});
} else {
loginContractInstance.recoverAddr.call(fixed_msg_sha, v_decimal, r,s, function(err, actual) {
console.log(`>>>>> Login - Failed login: Signature not matched:${addr} = ${actual}`);
saveFailedLoginAttempts(loginContractInstance, req, res);
});
}
});
} else {
console.log(`>>>>> Login - Failed login: User is locked`);
saveFailedLoginAttempts(loginContractInstance, req, res);
}
});
Y mi contrato inteligente,
contract Login {
event LoginAttempt(address sender, string password);
address private sender;
string private password;
function successfulLogin (address _sender, string _password) public {
LoginAttempt(_sender, _password);
sender = _sender;
password = _password;
}
function failedLogin (address _sender, string _password) public {
LoginAttempt(_sender, _password);
}
function recoverAddr(bytes32 msgHash, uint8 v, bytes32 r, bytes32 s) public pure returns (address) {
return ecrecover(msgHash, v, r, s);
}
function isSigned(address _addr, bytes32 msgHash, uint8 v, bytes32 r, bytes32 s) public pure returns (bool) {
return ecrecover(msgHash, v, r, s) == _addr;
}
Aquí está el resultado de esa llamada de función en mi consola,
¿Alguien puede ayudar en lo que me estoy perdiendo?
EDITAR
He corregido la función recoveryAddr.call para usar la entrada correcta. También descubrí que fixed_msg_sha
el problema es mío porque 0x
agregué const fixed_msg_sha = '0x' + web3.sha3(fixed_msg)
. se imprimió así0x0xf348f6a3d221a5e7e851292474330ca6e6cf6ad54572ee114233ab9b9225ab4f
Ahora el problema ha cambiado para devolver una dirección 0x,
su función de contrato inteligente:
function recoverAddr(bytes32 msgHash, uint8 v, bytes32 r, bytes32 s)
su código de fondo:
loginContractInstance.recoverAddr.call(addr, fixed_msg_sha, v_decimal, r,s, function(err, actual) {
¿ No crees que tenías la intención de pasar addr
como primer parámetro?
Sin embargo, no estoy seguro de por qué no se queja de "número no válido de argumentos para la función de solidez".
Si está usando esto para reconstruir las preimágenes: \x19Ethereum Signed Message:\n30
`que es lo que se proporciona en la publicación mediana, es incorrecto, la cadena de bytes adecuada es:
\x19Ethereum Signed Message:\n32
Observé el mismo ejemplo que usted y me quedé extremadamente atascado cuando experimenté por primera vez con la verificación de la firma, ya que es incorrecto (tal vez era correcto cuando se escribió la publicación mediana, pero ya no).
Tengo un contrato escrito que usa ecrecover y mensajes firmados por geth, puede consultar la declaración del prefijo de la firma aquí: https://github.com/postables/Postables-Payment-Channel/blob/7d2f91bb060f80b139cab72b5fdff79d116f6210/solidity/ChannelsV4. sol#L12 y observe que no coincide con lo que dio el autor de la publicación mediana.
La verificación de la firma real tiene lugar aquí:
Mi preferencia personal para firmar mensajes es usar python web3 + un nodo geth local, como lo demuestra este script de python:
https://github.com/postables/Postables-Payment-Channel/blob/develop/python/signer.py
const fixed_msg = \x19Ethereum Signed Message:\n${msg.length}${msg}
ya que es más ajustable.
Cristoforus Darryl Widjaya