Мне нужна помощь с проверкой адреса Ethereum. Я следую руководству по подписанию и проверке адреса Ethereum. Код на гитхабе . Меня смущает мой фактический результат адреса после запуска, loginContractInstance.recoverAddr.call(addr, fixed_msg_sha, v_decimal, r,s, function(err, actual) {
потому что он возвращает ноль.
Вот мой внутренний код ниже,
// 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);
}
});
И мой смарт-контракт,
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;
}
Вот результат вызова этой функции в моей консоли,
Может ли кто-нибудь помочь, что мне не хватает?
РЕДАКТИРОВАТЬ
Я исправил функцию recoveryAddr.call, чтобы она использовала правильный ввод. Я также узнал, что моя fixed_msg_sha
проблема, потому что я добавил 0x
в const fixed_msg_sha = '0x' + web3.sha3(fixed_msg)
. Это было напечатано так0x0xf348f6a3d221a5e7e851292474330ca6e6cf6ad54572ee114233ab9b9225ab4f
ваша функция смарт-контракта:
function recoverAddr(bytes32 msgHash, uint8 v, bytes32 r, bytes32 s)
ваш внутренний код:
loginContractInstance.recoverAddr.call(addr, fixed_msg_sha, v_decimal, r,s, function(err, actual) {
Не думаю, что вы намеревались передать addr
в качестве первого параметра?
Не уверен, почему он не жалуется на «недопустимое количество аргументов для функции прочности», хотя
Я знаю, что вы используете это для восстановления прообразов: \x19Ethereum Signed Message:\n30
`это то, что дано в сообщении среды. Это неверно, правильная строка байтов:
\x19Ethereum Signed Message:\n32
Я посмотрел на тот же пример, что и вы, и очень застрял, когда впервые экспериментировал с проверкой подписи, так как она неверна (может быть, это было правильно, когда писался средний пост, но не сейчас).
У меня есть написанный контракт, который использует ecrecover и сообщения, подписанные geth, вы можете взглянуть на объявление префикса подписи здесь: https://github.com/postables/Postables-Payment-Channel/blob/7d2f91bb060f80b139cab72b5fdff79d116f6210/solidity/ChannelsV4. sol#L12 и обратите внимание, что он не совпадает с тем, что дал автор поста на Medium.
Фактическая проверка подписи происходит здесь:
Лично я предпочитаю подписывать сообщения с помощью python web3 + локальный узел geth, как показано в этом скрипте python:
https://github.com/postables/Postables-Payment-Channel/blob/develop/python/signer.py
const fixed_msg = \x19Ethereum Signed Message:\n${msg.length}${msg}
поскольку он более настраиваемый.
Кристофорус Дэррил Виджая