I need help with Ethereum address verification. I'm following the tutorial on signing and validating Ethereum address. GitHub code. I'm confused by my actual result of the address after I ran loginContractInstance.recoverAddr.call(addr, fixed_msg_sha, v_decimal, r,s, function(err, actual) {
because it returns null.
Here is my backend code below,
// 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);
}
});
And my smart contract,
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;
}
Here is the result of that function call in my console,
Can anyone help what I'm missing on?
EDIT
I have corrected the recoverAddr.call function to use take the correct input. I have found out as well that my fixed_msg_sha
is the issue because I added 0x
in const fixed_msg_sha = '0x' + web3.sha3(fixed_msg)
. It was printed like this 0x0xf348f6a3d221a5e7e851292474330ca6e6cf6ad54572ee114233ab9b9225ab4f