Wie kann ich eine kryptografische Signatur verifizieren, die von einem Ethereum-Adressschlüsselpaar erstellt wurde?

Wenn ich eine kryptografische Signatur von einem Ethereum-Adressschlüsselpaar habe, wie kann ich diese Signatur verifizieren?

Antworten (1)

Solidity und Serpent haben ecrecoverzu diesem Zweck.

ecrecover(bytes32 data, uint8 v, bytes32 r, bytes32 s) gibt (Adresse) zurück

Die Funktionsargumente sind:

datawurde unterschrieben . Da es sich um 32 Bytes handelt, bedeutet dies normalerweise, dass die anfänglichen Daten zuerst auf 32 Bytes gehasht werden, bevor sie signiert werden.

v, r, sist die Signatur. ( vist die Wiederherstellungs-ID: ein 1-Byte-Wert, der das Vorzeichen und die Endlichkeit des Kurvenpunkts angibt; dieser Wert liegt im Bereich von [27, 30], jedoch erklärt das Ethereum-Protokoll die oberen beiden Möglichkeiten, die unendliche Werte darstellen, für ungültig)

Wichtiger Hinweis zu den Beispielen unten, sha3 ist Keccak-256 .

Hier ist ein Ausschnitt in 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;
    }
}

Hier ist ein Beispiel in Serpent :

def test_ecrecover(h, v, r, s):
    return(ecrecover(h, v, r, s))

Der entsprechende Testcode in Python (Requires bitcoinund ethereumPackages):

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)

ecrecoverVerwendet unter der Haube den ECDSARECOVER vorkompilierten Vertrag unter Adresse 1.


Hinweis: Geth und web3.eth.sign fügen der dataNachricht vor dem Signieren ein Präfix hinzu.

Die Sign-Methode berechnet eine Ethereum-spezifische Signatur mit: sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))).

Durch das Hinzufügen eines Präfixes zur Nachricht wird die berechnete Signatur als Ethereum-spezifische Signatur erkennbar. Dies verhindert Missbrauch, bei dem eine böswillige DApp willkürliche Daten (z. B. Transaktionen) signieren und die Signatur verwenden kann, um sich als das Opfer auszugeben.

verify()In diesem Fall muss das zweite Argument keccak256("\x19Ethereum Signed Message:\n", len(message), message)anstelle von sein keccak256(message).

Verwandte: ecrecover von Geth und web3.eth.sign

Obwohl dies bereits eine sehr gründliche Antwort ist, können Sie hinzufügen, was ecrecover im Falle einer guten oder ungültigen Signatur zurückgibt?
So wie ich es verstehe, gibt eine gute Signatur die Adresse zurück, die die Signatur durchgeführt hat. Eine fehlerhafte Signatur gibt eine andere Adresse zurück. Es gibt keine Möglichkeit zu sagen, ob eine Unterschrift gültig ist oder nicht, ohne auch die Adresse zu kennen, die die Unterschrift leisten sollte.
Aus den Solidity-Dokumenten auf ecrecover: "Stellen Sie die mit dem öffentlichen Schlüssel verknüpfte Adresse aus der Signatur der elliptischen Kurve wieder her oder geben Sie bei einem Fehler Null zurück."
Vielen Dank an den anonymen Redakteur, der den wichtigen Codekommentar hinzugefügt hat: "Sie müssen auch überprüfen, ob der Hash der Daten auch korrekt ist."
Wenn die Signatur falsch ist, erhalten Sie davon immer noch eine gültige Adresse. Müssen Sie den Unterzeichner also nur dazu bringen, die Adresse irgendwo in die ursprüngliche Nachricht aufzunehmen, um sie auf Richtigkeit zu überprüfen?
Oder umgekehrt @sudo, wenn der Hash falsch ist, erhalten Sie immer noch eine gültige, aber falsche Adresse.