Ethereum ecrecover Signaturüberprüfung und Verschlüsselung

Die Frage des Signierens und Verifizierens von Signaturen mit Solidity wurde in diesen Fragen gestellt, die ich beide zu untersuchen versucht habe:

Wie kann ich ein Datenelement mit dem privaten Schlüssel einer Ethereum-Adresse signieren?

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

Es gibt jedoch immer noch Informationen, die mir anscheinend fehlen.

Zunächst möchte ich mit der Frage nach der Unterschrift beginnen. Im Beispiel wird die Zeichenfolge Schoolbusvon der Adresse signiert 0xd1ade25ccd3d550a7eb532ac759cac7be09c2719, und die resultierende Signatur ist 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601.

So weit, ist es gut. Nun möchte ich überprüfen, ecrecoverob die Signatur für die angegebene Adresse und das angegebene Datum tatsächlich korrekt ist. Die Sache ist, ecrecovernimmt vier Argumente: ecrecover(h, v, r, s). Abgesehen davon h, dass es der Hash ist und {v, r, s}irgendwie die Signatur umfasst, wofür stehen v, r und s genau? Und wie erhalte ich alle notwendigen Werte aus der einzelnen Zeichenfolge 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601?

Was ich weiß, ist, dass ecrecovereine Adresse zurückgegeben wird, und die Überprüfung einer Signatur besteht im Wesentlichen darin, die resultierende Adresse mit der erwarteten zu vergleichen. Doch das ganze Prozedere erscheint unnötig kompliziert.

Abgesehen davon habe ich mich auch gefragt, wie ich eine Signatur erstellen könnte, entweder so 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601oder {h, v, r, s}nur mit Solidity, ohne den RPC-JSON-Umweg, wie es in der Frage der Fall ist – vorausgesetzt, ich kenne einen privaten Schlüssel?

Schauen Sie sich ethereum.stackexchange.com/questions/1777/… an. Hier liste ich auch das Verfahren zum Extrahieren von r, v und s aus der Signaturzeichenfolge auf. Ich stimme zu, dass dieses Verfahren etwas zu kompliziert ist, und ich habe dieses Problem hier geäußert: github.com/ethereum/EIPs/issues/79
Ich fürchte, dass die fragliche Frage nicht in Solidity enthalten ist. Was ich zu erreichen versuche, muss im Rahmen eines Vertrags ausgeführt werden.
Können Sie ein wenig erläutern, warum Sie etwas in einem Vertrag unterschreiben möchten? Wie bereits erwähnt, wird dadurch der private Schlüssel des Unterzeichners allen zugänglich gemacht
Ich möchte lediglich eine Signatur im oben angegebenen Format innerhalb eines Vertrages verifizieren. Der Signaturteil wäre nur für Komponententests.
Das Überprüfungsverfahren erfolgt in einem Soliditätsvertrag in der von mir verlinkten Frage
Der Aufruf ecrecoverist, ja. Aber ich habe keine Ausführungsumgebung in JavaScript, die es umgibt, die in der Lage wäre, die Signaturzeichenfolge in den separaten Komponenten vorzubereiten, bevor sie in einen Solidity-Vertrag eingespeist wird. Der Vertrag selbst muss in der Lage sein, die rohe Signaturzeichenfolge zu verarbeiten.
Im Prinzip suche ich möglicherweise nur nach Solidity-Äquivalenten von web3.toDecimalund String.prototype.slice. Ich probiere alle Antworten in einem Vertrag aus, sobald sie kommen.
@arik "Bei der Überprüfung einer Signatur geht es im Wesentlichen darum, die resultierende Adresse mit der erwarteten zu vergleichen" ist nicht das, was ecrecoveres tut. Es vergleicht den übergebenen Hash mit der aus der Signatur entschlüsselten Hash-Nachricht, um festzustellen, ob sie übereinstimmen, und gibt dann die Adresse zurück, wenn sie wahr ist.

Antworten (2)

v, r und s sind Parameter, die aus der Signatur geparst werden können. Hier ist ein gutes Beispiel aus der utils-Bibliothek von ethereumjs:

  var sig = secp256k1.sign(msgHash, privateKey)
  var ret = {}
  ret.r = sig.signature.slice(0, 32)
  ret.s = sig.signature.slice(32, 64)
  ret.v = sig.recovery + 27

Beachten Sie, wie Sie jeden Wert einer bestimmten Signatur parsen können.

Auch wenn Sie zwei verschiedene Nachrichten mit demselben privaten Schlüssel signieren können, generiert der Signaturprozess (intern) einen zufälligen Nonce-Wert (k), der als Teil der Berechnung verwendet wird und für jede generierte Signatur unterschiedlich sein muss.

r und s zusammen mit dem zugehörigen öffentlichen Schlüssel helfen bei der Validierung, ob die Signatur echt ist.

Hinweis: Ich bin kein Kryptograf. Dies ist, was ich ausgegraben habe, um die gleichen Fragen zu beantworten, die Sie haben. Ich würde vorschlagen, sich einige der Online-Ressourcen für elliptische Kurven anzusehen.

Aside from this, I was also wondering how I could produce a signature, either like this 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601 or a set of {h, v, r, s} using Solidity alone, without the RPC-JSON detour as is the case in the question – vorausgesetzt, ich kenne einen privaten Schlüssel?

Das Problem, das Sie beim Generieren einer Signatur in Solidity haben würden, besteht darin, dass Sie den privaten Schlüssel offenlegen müssten. Alternativ können Sie eine Signatur außerhalb des normalen Ethereum-Transaktionsprozesses mithilfe einer der vielen Bibliotheken für elliptische Kurven generieren und diese resultierende Signatur an einen Vertrag senden.

Danke für die Antwort! Nun, wenn ich nur die Signaturzeichenfolge habe, wie bekomme ich das Signaturobjekt daraus? Die Signaturzeichenfolge selbst enthält leider keine recoveryEigenschaft. Nur um sicherzugehen: Ist der Hash für ecrecoversha256 notwendig?
Gibt es eine Möglichkeit, v neu zu berechnen? Ich fürchte ecrecover, wird nicht funktionieren, ohne den richtigen Wert zu übergeben.
IIUC, wenn eine Signatur DER-codiert ist, speichert sie nur die r- und s-Punkte und wirft "v" weg. Wenn ich einen "v"-Wert angeben möchte, probiere ich einfach beide aus. Wo also pubkey_decompressed der öffentliche Schlüssel ist, der die Ethereum-Adresse erstellt hat: v_but_not_really, r, s = bitcoin.der_decode_sig(sig) for possible_v in [27, 28]: possible_pub = bitcoin.encode_pubkey(bitcoin.ecdsa_raw_recover(msg_hash, (possible_v, r , s)), 'hex') if pubkey_decompressed == possible_pub: return possible_v
In der Zeichenfolge, die bei Verwendung von eth.sign zurückgegeben wird, ist v enthalten. Die letzten beiden Hex-Zeichen stehen für v. Mehr dazu hier: ethereum.stackexchange.com/questions/1777/…
Welchen Client oder welche Umgebung benötige ich, um diesen Signaturprozess durchzuführen? " var sig = secp256k1.sign(msgHash, privateKey) var ret = {} ret.r = sig.signature.slice(0, 32) ret.s = sig.signature.slice(32, 64) ret.v = sig .Erholung + 27"

Wofür genau stehen v, r und s?

  • rist der R.xWert des Signaturpunktes R.
  • sist der Unterschriftsbeweis fürR.x
  • vist ein Wiederherstellungsparameter, der verwendet wird, um die Signaturüberprüfung zu erleichtern.

vist nicht erforderlich, aber oft enthalten. Aber was ist v?

Da die Signatur nur die xKoordinate des Punktes enthält R, gibt es entweder 0, 1, 2, 3 oder 4 übereinstimmende yKoordinaten über der elliptischen Kurve Secp256k1. Diese vier potenziellen Kandidaten sind in etwas namens verschlüsselt recovery_id.

Eine Wiederherstellungs-ID kann die Werte 0..3abhängig von den folgenden Bedingungen haben:

  • Ist R.ygerade und R.xkleiner als die Kurvenordnung n:recovery_id := 0
  • Ist R.y ungerade und R.xkleiner als die Kurvenordnung n:recovery_id := 1
  • Ist R.ygerade und R.x mehr als die Kurvenordnung n:recovery_id := 2
  • Ist R.y ungerade und R.x mehr als die Kurvenreihenfolge n:recovery_id := 3

Jetzt wissen wir, wie wir an die Wiederherstellungs-ID kommen. vist einfach v = recory_id + 27für Bitcoin. Zusätzlich zu den vWerten von 27..30, die nur die Wiederherstellungs-ID widerspiegeln, gibt es auch die Idee, komprimierte öffentliche Schlüssel wiederherzustellen, wobei dieselbe Wiederherstellungs-ID, aber eine vvon v = recovery_id + 31.

Aber wir reden nicht über Bitcoin, also sollten Sie sich zu guter Letzt EIP-155 ansehen, weil wir den + 27Teil, den Bitcoin verwendet hat, um den Replay-Schutz zu verhindern, nicht mehr verwenden:

v = chain_id * 2 + 35 + recovery_id

Spiegelt in Ethereum vdie Kette für den Replay-Schutz und die ID für die Signaturwiederherstellung wider.

Und wie erhalte ich alle notwendigen Werte aus der einzelnen Zeichenfolge 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601?

Dies ist nur eine verkettete Zeichenfolge "#{v}#{r}#{s}"mit:

  • v = 0x2a
  • r = 0xc19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407
  • s = 0x466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601

Das vist 42.

chain_id = (v - 35) / 2

Jetzt können wir überprüfen, dass die vvon 42 nur auf der Kette mit der ID 3 (Ropsten) gültig ist.

Was ich weiß, ist, dass ecrecovereine Adresse zurückgegeben wird, und die Überprüfung einer Signatur besteht im Wesentlichen darin, die resultierende Adresse mit der erwarteten zu vergleichen. Doch das ganze Prozedere erscheint unnötig kompliziert.

Ich weiß, dass dies keine Frage ist, aber so funktioniert die Kryptografie mit elliptischen Kurven buchstäblich: Es sind nur mathematische Operationen mit verschiedenen Punkten auf einer Kurve.

Eine Adresse ist nur eine hübsch formatierte Version des öffentlichen Schlüssels; Der öffentliche Schlüssel ist nur ein Punkt auf der elliptischen Kurve Secp256k1.

Eine Unterschrift ist nur ein weiterer Punkt. Und wenn Sie Public-Key-Magic und Signatur-Magic anwenden, haben Sie am Ende dieses mathematischen Prozesses zwei Punkte (öffentliche Schlüssel) und wenn es sich um exakte Übereinstimmungen handelt, kann die Signatur als verifiziert betrachtet werden .

Das ecrecoverZurückgeben von an addressdient nur Ihrer Bequemlichkeit: Sie können direkt vergleichen, ob die Signaturadresse mit der Unterzeichneradresse übereinstimmt - und das ist in Solidity viel einfacher zu bewerkstelligen als mit unkomprimierten öffentlichen Schlüsseln umzugehen.

Ich hoffe, das bringt etwas Licht in diese Frage.