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?
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 Schoolbus
von der Adresse signiert 0xd1ade25ccd3d550a7eb532ac759cac7be09c2719
, und die resultierende Signatur ist 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601
.
So weit, ist es gut. Nun möchte ich überprüfen, ecrecover
ob die Signatur für die angegebene Adresse und das angegebene Datum tatsächlich korrekt ist. Die Sache ist, ecrecover
nimmt 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 ecrecover
eine 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 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601
oder {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?
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.
recovery
Eigenschaft. Nur um sicherzugehen: Ist der Hash für ecrecover
sha256 notwendig?ecrecover
, wird nicht funktionieren, ohne den richtigen Wert zu übergeben.Wofür genau stehen v, r und s?
r
ist der R.x
Wert des Signaturpunktes R
.s
ist der Unterschriftsbeweis fürR.x
v
ist ein Wiederherstellungsparameter, der verwendet wird, um die Signaturüberprüfung zu erleichtern.v
ist nicht erforderlich, aber oft enthalten. Aber was ist v
?
Da die Signatur nur die x
Koordinate des Punktes enthält R
, gibt es entweder 0, 1, 2, 3 oder 4 übereinstimmende y
Koordinaten über der elliptischen Kurve Secp256k1. Diese vier potenziellen Kandidaten sind in etwas namens verschlüsselt recovery_id
.
Eine Wiederherstellungs-ID kann die Werte 0..3
abhängig von den folgenden Bedingungen haben:
R.y
gerade und R.x
kleiner als die Kurvenordnung n
:recovery_id := 0
R.y
ungerade und R.x
kleiner als die Kurvenordnung n
:recovery_id := 1
R.y
gerade und R.x
mehr als die Kurvenordnung n
:recovery_id := 2
R.y
ungerade und R.x
mehr als die Kurvenreihenfolge n
:recovery_id := 3
Jetzt wissen wir, wie wir an die Wiederherstellungs-ID kommen. v
ist einfach v = recory_id + 27
für Bitcoin. Zusätzlich zu den v
Werten 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 v
von v = recovery_id + 31
.
Aber wir reden nicht über Bitcoin, also sollten Sie sich zu guter Letzt EIP-155 ansehen, weil wir den + 27
Teil, den Bitcoin verwendet hat, um den Replay-Schutz zu verhindern, nicht mehr verwenden:
v = chain_id * 2 + 35 + recovery_id
Spiegelt in Ethereum v
die 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 v
ist 42.
chain_id = (v - 35) / 2
Jetzt können wir überprüfen, dass die v
von 42 nur auf der Kette mit der ID 3 (Ropsten) gültig ist.
Was ich weiß, ist, dass
ecrecover
eine 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 ecrecover
Zurückgeben von an address
dient 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.
MrChico
arik
MrChico
arik
MrChico
arik
ecrecover
ist, 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.arik
web3.toDecimal
undString.prototype.slice
. Ich probiere alle Antworten in einem Vertrag aus, sobald sie kommen.Garen Vartanian
ecrecover
es 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.