Если у меня есть криптографическая подпись из пары ключей адреса Ethereum, как я могу проверить эту подпись?
Для этого есть Solidity и Serpent ecrecover
.
ecrecover(bytes32 data, uint8 v, bytes32 r, bytes32 s) возвращает (адрес)
Аргументы функции:
data
это то, что было подписано . Поскольку это 32 байта, это обычно означает, что исходные данные сначала хэшируются до 32 байтов, прежде чем они будут подписаны.
v
, r
, s
это подпись. ( v
это идентификатор восстановления: 1-байтовое значение, указывающее знак и конечность точки кривой; это значение находится в диапазоне [27, 30], однако протокол Ethereum объявляет две верхние возможности, представляющие бесконечные значения, недействительными)
Важное примечание к приведенным ниже примерам: sha3 — это Keccak-256 .
Вот фрагмент в Solidity :
contract Auth {
function verify(address p, bytes32 hash, uint8 v, bytes32 r, bytes32 s) constant returns(bool) {
// Note: this only verifies that signer is correct.
// You'll also need to verify that the hash of the data
// is also correct.
return ecrecover(hash, v, r, s) == p;
}
}
Вот пример в Змее :
def test_ecrecover(h, v, r, s):
return(ecrecover(h, v, r, s))
Соответствующий тестовый код на Python (требуется bitcoin
и ethereum
упаковывается):
import bitcoin as b
from ethereum import tester, utils
class TestECRecover(object):
CONTRACT = """
def test_ecrecover(h, v, r, s):
return(ecrecover(h, v, r, s))
"""
def setup_class(cls):
cls.s = tester.state()
cls.c = cls.s.abi_contract(cls.CONTRACT)
cls.snapshot = cls.s.snapshot()
def setup_method(self, method):
self.s.revert(self.snapshot)
def test_ecrecover(self):
priv = b.sha256('some big long brainwallet password')
pub = b.privtopub(priv)
msghash = b.sha256('the quick brown fox jumps over the lazy dog')
V, R, S = b.ecdsa_raw_sign(msghash, priv)
assert b.ecdsa_raw_verify(msghash, (V, R, S), pub)
addr = utils.sha3(b.encode_pubkey(pub, 'bin')[1:])[12:]
assert utils.privtoaddr(priv) == addr
result = self.c.test_ecrecover(utils.big_endian_to_int(msghash.decode('hex')), V, R, S)
assert result == utils.big_endian_to_int(addr)
Под капотом ecrecover
используется ECDSARECOVER
предварительно скомпилированный контракт , расположенный по адресу 1.
Примечание. Geth и web3.eth.sign добавят к data
сообщению префикс перед подписью.
Метод sign вычисляет специфичную для Ethereum подпись с помощью: sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))).
Добавление префикса к сообщению делает рассчитанную подпись распознаваемой как подпись, специфичная для Ethereum. Это предотвращает неправомерное использование, когда вредоносное DApp может подписывать произвольные данные (например, транзакцию) и использовать подпись, чтобы выдать себя за жертву.
В этом случае второй аргумент to verify()
должен быть keccak256("\x19Ethereum Signed Message:\n", len(message), message)
вместо keccak256(message)
.
Связано: ecrecover от Geth и web3.eth.sign
Джей Би
ryepdx
ЗМиттон
эт
судо
Гарен Вартанян