Я пытался использовать ecrecover()
для проверки подписи сообщения.
Я просмотрел множество ссылок здесь и в других местах, например:
и другие.
Но я все еще не могу ecrecover()
вернуть адрес подписи. Поэтому я надеюсь, что кто-то может указать на какую-то глупую ошибку, которую я совершаю.
Вот мой код:
pragma solidity ^0.4.0;
contract test {
function test() {
}
function verify(bytes32 _message, uint8 _v, bytes32 _r, bytes32 _s) constant returns (address) {
address signer = ecrecover(_message, _v, _r, _s);
return signer;
}
}
Затем в geth я делаю:
> var msg = web3.sha3("hello")
"0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8"
> eth.accounts[0] -->
"0x7156526fbd7a3c72969b54f64e42c10fbb768c8a"
> var sig = eth.sign(eth.accounts[0], msg)
"0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac80388256084f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada1c"
> var r = sig.substr(0,66)
"0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608"
> var s = "0x" + sig.substr(66,64)
"0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada"
> var v = 28
28
> test.verify(msg,v,r,s)
"0x33692ee5cbf7ecdb8ca43ec9e815c47f3db8cd11"
...что, конечно, НЕeth.accounts[0]
Я совершенно озадачен. Есть ли кто-нибудь, кто может увидеть, что я делаю неправильно?
Я тоже очень долго застревал на этом вопросе.
Итак, решение таково: добавьте эту строку префикса в свой смарт-контракт Solidity.
function verify(bytes32 hash, uint8 v, bytes32 r, bytes32 s) constant returns(bool) {
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
bytes32 prefixedHash = keccak256(prefix, hash);
return ecrecover(prefixedHash, v, r, s) == (Your Address);
}
32
в конце prefix
соответствует длина сообщения! github.com/ethereum/wiki/wiki/JSON-RPC#eth_signAdd this prefix string to your Solidity smart contract
а в случае, если я не контролирую смарт-контракт ?Согласно вопросу № 3731 :
Geth добавляет строку
\x19Ethereum Signed Message:\n<length of message>
ко всем данным перед их подписанием ( https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign ). Если вы хотите проверить такую подпись от Solidity, вам нужно добавить ту же строку в Solidity перед выполнением ecrecovery.
Вот рабочий пример, который я тестировал с помощью truffle :
Пример.sol
pragma solidity ^0.4.0;
contract Example {
function testRecovery(bytes32 h, uint8 v, bytes32 r, bytes32 s) returns (address) {
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
bytes32 prefixedHash = sha3(prefix, h);
address addr = ecrecover(prefixedHash, v, r, s);
return addr;
}
}
пример.js (тест)
var Example = artifacts.require('./Example.sol')
var Web3 = require('web3')
var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'))
contract('Example', (accounts) => {
var address = accounts[0]
it('ecrecover result matches address', async function() {
var instance = await Example.deployed()
var msg = '0x8CbaC5e4d803bE2A3A5cd3DbE7174504c6DD0c1C'
var h = web3.sha3(msg)
var sig = web3.eth.sign(address, h).slice(2)
var r = `0x${sig.slice(0, 64)}`
var s = `0x${sig.slice(64, 128)}`
var v = web3.toDecimal(sig.slice(128, 130)) + 27
var result = await instance.testRecovery.call(h, v, r, s)
assert.equal(result, address)
})
})
Текущий тест:
$ truffle test
Using network 'development'.
Compiling ./contracts/Example.sol...
Contract: Example
✓ ecrecover result matches address (132ms)
1 passing (147ms)
Вероятно, лучше сделать префикс на уровне приложения, а не в контракте солидности, так как это будет дешевле.
Связанный
Итак, спасибо Адилу (см. выше), вот готовый код, который я использовал, который определенно работает с процессом, описанным мной выше:
прочность прагмы ^0,4,0; тест контракта { функциональный тест () { } Функция проверки (bytes32 _message, uint8 _v, bytes32 _r, bytes32 _s) возвращает константу (адрес) { префикс памяти в байтах = "\x19Ethereum Signed Message:\n32"; bytes32 prefixedHash = sha3 (префикс, _сообщение); подписывающий адрес = ecrecover (prefixedHash, _v, _r, _s); обратно подписывающий; } }
v+27
. github.com/ethereum/go-ethereum/issues/2053v+27
не работает там, где я видел, но кто-то использует его по какой-то причинеВы уверены, что используете правильные типы данных? Несколько недель назад я создал простое приложение для проверки с помощью ecrecover.
Код можно посмотреть здесь: https://github.com/Shultzi/validator/blob/master/client/main.js .
Как видите, я прошел h
, r
и s
не как , buffers
а hex
. Также убедитесь, что в вашем смарт-контракте v
значение равноuint8
В следующей статье может быть объяснена часть «\x19EthereumSignedMessage».
https://blog.ricmoo.com/verifying-messages-in-solidity-50a94f82b2ca
В ECDSA компании OpenZeppelin есть инструмент для создания таких упакованных сообщений, а также для устранения дополнительных нестандартных ситуаций в ECDSA.
Я написал статью, описывающую, как я считаю, правильный способ использования hashMessage() и sign() web3, ecrecover() Solidity и библиотеки ECDSA Open Zeppelin.
https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/cryptography/ECDSA.sol
https://medium.com/@yaoshiang/ethereums-ecrecover-openzeppelin-s-ecdsa-and-web3-s-sign-8ff8d16595e1
Гринонлайн
пользователь53765
Шейн Фонтейн
Николя Массар