Проверка подписи Ethereum не соответствует

Чего я хочу добиться, так это подписать сообщение, а затем проверить подпись, проверена ли она по тому же адресу или нет.

Контракт на вызов метода ecrecover для проверки адреса

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

Код 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);

Выход

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

Вы можете ясно видеть, что окончательный указанный адрес не соответствует тому, который использовался для подписи сообщения.

Примечание. Я пробую это на своем частном блокчейне.

Вопрос : Какой шаг необходимо исправить для достижения желаемого результата (т.е. конечный адрес должен совпадать с адресом учетной записи, используемым для подписи в этом случае, который равен 0x890bd380e472df5b8bab22075c6a5d4f0b84415c )?

Пытался использовать ethereumjs-util со значением подписи, сгенерированным baove, но получил тот же результат.

  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);

Вывод - окончательный адрес 2: 0x0609b9fae476d8b844716e3a0a6a3b5b7a5a2cdf "(то есть тот же адрес)

Ответы (1)

Вам необходимо добавить к сообщению префикс строки "\x19Ethereum Signed Message:\n" и длину сообщения.

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

А затем используйте строку с префиксом в ecrecover.

код взят из ответа здесь https://ethereum.stackexchange.com/a/12684/

Большое спасибо за то, что поделились подробностями в этом отношении. Теперь я могу расшифровать адрес, с помощью которого была сгенерирована подпись.