Si tengo una firma criptográfica de un par de claves de direcciones de Ethereum, ¿cómo puedo verificar esa firma?
Solidez y Serpiente tienen ecrecover
para este fin.
ecrecover(bytes32 datos, uint8 v, bytes32 r, bytes32 s) devuelve (dirección)
Los argumentos de la función son:
data
es lo que se firmó . Dado que son 32 bytes, eso generalmente significa que los datos iniciales se codifican primero a 32 bytes, antes de que se firmen.
v
, r
, s
es la firma. ( v
es la identificación de recuperación: un valor de 1 byte que especifica el signo y la finitud del punto de la curva; este valor está en el rango de [27, 30], sin embargo, el protocolo Ethereum declara inválidas las dos posibilidades superiores, que representan valores infinitos)
Nota importante con los ejemplos a continuación, sha3 es Keccak-256 .
Aquí hay un fragmento en 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;
}
}
Aquí hay un ejemplo en Serpent :
def test_ecrecover(h, v, r, s):
return(ecrecover(h, v, r, s))
El código de prueba correspondiente en Python (requisitos bitcoin
y ethereum
paquetes):
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)
Bajo el capó, ecrecover
utiliza el ECDSARECOVER
contrato precompilado ubicado en la dirección 1.
Nota: Geth y web3.eth.sign agregarán un prefijo al data
mensaje antes de firmar.
El método sign calcula una firma específica de Ethereum con: sign(keccak256("\x19Ethereum Signed Message:\n" + len(mensaje) + mensaje))).
Al agregar un prefijo al mensaje, la firma calculada se puede reconocer como una firma específica de Ethereum. Esto evita el uso indebido en el que una DApp maliciosa puede firmar datos arbitrarios (por ejemplo, transacciones) y usar la firma para hacerse pasar por la víctima.
Para este caso, el segundo argumento verify()
debe ser keccak256("\x19Ethereum Signed Message:\n", len(message), message)
en lugar de keccak256(message)
.
Relacionado: ecrecover de Geth y web3.eth.sign
JB
ryepdx
ZMitton
ética
sudo
garen vartanian