Analoges web3.eth.accounts.sign (von web3js) in web3py

In der Implementierung von web3js gibt es eine Funktion web3.eth.accounts.sign. Aber ich kann das genaue Äquivalent in web3py nicht finden. Ich sehe das nicht. Ich habe etwas Ähnliches gefunden – die signHash-Funktion (Link https://web3py.readthedocs.io/en/stable/web3.eth.account.html#sign-a-message ). Diese Dokumentation besagt, dass derselbe Hashing-Mechanismus, aber als Ergebnis die Ausführung nicht dasselbe zurückgibt wie in web3js (web3.eth.accounts.sign).

Ich habe diese Funktion in web3js verwendet, um die Signatur abzurufen (und dann die ECDSA-Bibliothek (auf Solidity) verwendet, um den Unterzeichner abzurufen. Auf web3js funktioniert es korrekt (aber auf web3py - nein). Ich verbinde mich über Infura mit dem Testnetzwerk (ropsten).

Auf web3js (wobei msg - was signiert ist):

let signature = await web3.eth.accounts.sign(msgHash, '0x' + privateKeyUser);
console.log('signature ='+signature.signature);

Auf web3py (ich versuche es, funktioniert aber nicht):

signature = web3.eth.account.signHash(msgHash, '0x' + privateKeyUser)
print('signature ='+signature.signature.hex())

And for example in variable "msgHash" value: 0x058c3b4c8e5dc4632b5c6b861b2c1861d53e426dc673c907ddf2651942b0f230 And at the output of web3js function (web3.eth.accounts.sign), we get signature: 0xd19241ed816026e846c8511e03a468aa6e038165ecb3c2229eee38b04c64b235408389dfad2b65d776dba236e7de1b63fdb6b2579e70c4ce9ad1b09a35da96521c And this is the correct value. Web3py hat einen anderen Wert.

Was ist in web3py genau analog dazu, wie diese web3.eth.accounts.sign-Funktion in web3js funktioniert? Danke schön!

Es wäre hilfreich, wenn Sie eine Beispielnachricht bereitstellen würden, die Sie zu signieren versuchen, sowie die Rohdaten (hexadezimal codiert), die web3.jserzeugt werden.
Es wäre auch gut zu wissen, ob Sie einen Remote-Knoten zum Signieren/Verarbeiten von Schlüsseln verwenden oder ob der private Schlüssel zum Signieren im Skript für verfügbar ist web3.js. (Es gibt diese Unterscheidung in web3.py.)
Im Allgemeinen wurden in v5 Komfortmethoden für das strukturierte EIP-712-Signieren hinzugefügtweb3.py ; Die stableDokumente, auf die Sie verlinken, sind v4. Klären Sie, ob Sie speziell v4 benötigen oder ob v5 auch akzeptabel ist.
... Und da Sie neu bei SE sind: Diese Klarstellungen sollten als Änderungen an Ihrer ursprünglichen Frage erfolgen. (Willkommen! :D)
Danke für die Hilfe! Ja, ich bin neu hier :) Ich habe weitere Informationen hinzugefügt.
Hilf mir bitte. Ich habe in meiner ersten Frage weitere Informationen hinzugefügt. Ich weiß immer noch keine Antwort.
Dazu - "Im Allgemeinen wurden in v5 praktische Methoden für das strukturierte EIP-712-Signieren zu web3.py hinzugefügt; die stabilen Dokumente, auf die Sie verlinken, sind v4. Klären Sie, ob Sie speziell v4 benötigen oder ob v5 auch akzeptabel ist."
(Ende meines vorherigen Beitrags) Ich habe beide Versionen ausprobiert - 4 und 5. Davor habe ich Version 5 nicht ausprobiert (weil sie meines Wissens nach instabil ist). In Version 5 sehe ich die Möglichkeit, mit der Funktion "send_message" zu arbeiten. Wenn ich das richtig verstehe, muss eine Instanz der Klasse "SignableMessage" (aus eth_account.messages) übergeben werden. Aber ich verstehe nicht bis zum Ende, welche richtigen Parameter für die Initialisierung dieser Instanz.
@Alex Willkommen beim Stapelaustausch! Diese Frage würde verbessert, indem ein privater Schlüssel (offensichtlich ein "Brenner" -Schlüssel, da er öffentlich gemacht wird) und das erwartete Signaturergebnis hinzugefügt werden, um es vollständig reproduzierbar zu machen. Siehe stackoverflow.com/help/minimal-reproducible-example
@carver, ich habe in der ersten Beschreibung dieser Frage Codestücke gezeigt, die mein Problem beschreiben. Aber ich kann auch hinzufügen, dass ich dann die Signatur an den Smart Contract übergebe und die ECDSA-Bibliothek auf Solidity (von OpenZeppelin) verwende - Funktion ECDSA.recover für den Extraktunterzeichner.
@carver Ich habe in der ursprünglichen Beschreibung das erwartete Ergebnis der Signatur hinzugefügt.

Antworten (3)

Da Sie in Kommentaren erwähnt haben, dass Sie offen für die Verwendung von web3.py v5 sind, ist hier der v5-Ansatz zum Signieren einer Nachricht :

from eth_account import Account, messages

msg_hash_hex = "058c3b4c8e5dc4632b5c6b861b2c1861d53e426dc673c907ddf2651942b0f230"
private_key_hex = "b25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364"

#// This part prepares "version E" messages, using the EIP-191 standard
message = messages.encode_defunct(hexstr=msg_hash_hex)

#// This part signs any EIP-191-valid message
signed_message = Account.sign_message(message, private_key=private_key_hex)
print("signature =", signed_message.signature.hex())

Wenn Sie mehr über EIP-191 erfahren möchten, sehen Sie sich die ursprüngliche Beschreibung von EIP-191 an . Es ist kurz und lesbar.

Dieses Snippet entspricht dem Javascript:

msgHash = "0x058c3b4c8e5dc4632b5c6b861b2c1861d53e426dc673c907ddf2651942b0f230"
privateKeyUser = "b25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364"

// web3.js sign() *only* supports "version E" EIP-191 signing
// so it adds the preamble for you.
let signature = await web3.eth.accounts.sign(msgHash, '0x' + privateKeyUser);
console.log('signature ='+signature.signature);

Beachten Sie, dass die Javascript- sign()Methode eher "beliebige Daten signiert" als einen Nachrichten-Hash. Obwohl Sie es also zuerst zu hashen scheinen, könnten Sie stattdessen die ursprüngliche Nachricht signieren.

Bereiten Sie in der Python-Version die Originalnachricht zum Signieren vor mit: encode_defunct(text=original_message).

Danke für die Antwort! Aber ich habe Ihren Rat nicht durchgesetzt:
1) In der Version mit web3py habe ich einen Fehler: "AttributeError: 'bytes' object has no attribute 'encode'" Ich habe die Variable "msg_hash" in Text konvertiert. Zeile mit "encode_defunct" wurde zu: "message = encode_defunct(text="0x058c3b4c8e5dc4632b5c6b861b2c1861d53e426dc673c907ddf2651942b0f230")"
Und danach startete er ohne Fehler. und das Ergebnis ist: 0x4ef46c84d3b33927369c69da0aa46328a80c88f747ee33e9a597e76e8cf8a723642302bf793c1b80b8979a97416ff64423f0b4cad8a1f0e5e141b3f2a219b
2) In der Version mit web3js habe ich keine Fehler. Und Ergebnis: 0xdccea59712c525f67783bc2c6bb5add55447d3f2122f30eccb602c3e629a609f2a13c74c32fcb15799c94d3e00753c7264aee93339b327c2130e2f02ce4abb5c1 Ergebnisse sind nicht gleich, wie Sie sehen können.
Wie Sie sehen können, sind die Ergebnisse nicht gleich. Zur Information: Ich habe die Version von web3py - 5.0.0b2 und die Version von web3js - 1.0.0-beta.55
Ah, entschuldigen Sie den Tippfehler in encode_defunct. Ich habe die Antwort aktualisiert und erhalte das gleiche Ergebnis wie mit web3js.
Geprüft, jetzt funktioniert es richtig! @Carver, vielen Dank!

Es ist schwer zu sagen, ohne den Inhalt aller Variablen, einschließlich der Schlüssel, zu sehen.

Aber mein Bauchgefühl ist, dass Sie rohe Bytes und hexadezimale ASCII-Strings mischen - einige der Variablen sind nicht das, was Sie denken.

Können Sie Ihre Frage nach Möglichkeit mit vielen Ausdrucken und Ausgaben bearbeiten, um sie zu vergleichen?

Danke für die Antwort! Ich muss eine Variable schreiben, wo der private Schlüssel ist? Ich denke, das ist nur eine Sache, die hier fehlt. Datenvermischung - meiner Meinung nach habe ich sie hier explizit als Strings geschrieben). Bitte korrigieren Sie mich, wenn ich Sie falsch verstanden habe.

Für alle, die hierher gekommen sind mit web3.py < v5:

Verwenden Sie defunct_hash_message für die Nachricht, bevor Sie signHash.

from eth_account.messages import defunct_hash_message
prepared_message = defunct_hash_message(primitive=msgHash)
signature = web3.eth.account.signHash(prepared_message, '0x' + privateKeyUser)
print('signature =' + signature.signature.hex())