Wie soll ich das Passwort des Benutzers in einem Smart Contract speichern?

Zuerst dachte ich, ich könnte einfach Folgendes verwenden private:

mapping (address => bytes32) private userPassword;

und so prüfen Sie einfach, ob das eingegebene Passwort richtig ist:

function enter(bytes32 password) {
   if (password == userPassword[msg.sender])
      //do smth
}

Aber dann habe ich das in solidity docs gelesen:

Alles, was in einem Vertrag steht, ist für alle externen Beobachter sichtbar. Wenn Sie etwas privat machen, wird nur verhindert, dass andere Verträge auf die Informationen zugreifen und diese ändern, aber sie sind dennoch für die ganze Welt außerhalb der Blockchain sichtbar.

Also, wenn ich es richtig verstanden habe, kann jeder die Werte der gespeicherten Passwörter sehen, selbst wenn ich die "private" Sichtbarkeit verwende. Wie soll ich dann Informationen speichern, die nicht öffentlich sein sollten?

Antworten (5)

Benutzer (Verträge, vertrauenswürdige Maschinen, andere Verträge) werden anhand ihrer Ethereum-Adresse identifiziert.

Anstatt ihre Kennwörter zu speichern, verwenden Sie msg.sendersie zur Authentifizierung.

Da niemand unbefugt teilnehmen soll, benötigen Sie eine Liste mit berechtigten Adressen. Sie erstellen Funktionen zum Hinzufügen/Entfernen von Benutzern und stellen sicher, dass nur der autorisierte Administrator (normalerweise Eigentümer genannt) auf diese Vertragsfunktionen zugreifen darf.

Die Zugriffskontrollliste wäre eine Liste von Ethereum-Adressen.

Einige organisatorische Ideen hier: Gibt es gut gelöste und einfache Speichermuster für Solidity?

Und hier: https://medium.com/@robhitchens/solidity-crud-part-1-824ffa69509a

Ich hoffe es hilft.

Aber was ist, wenn ich nicht weiß, wer meinem Vertrag beitreten wird? Ich möchte nur jemandem ein Passwort geben, damit er es einfach eingeben kann. Weil ich seine Ethereum-Adresse nicht im Voraus kenne, um ihn zu authentifizieren.
Wenn Sie „jemand“ (dh einer bestimmten Person) ein Passwort geben, können Sie diese Person genauso gut bitten, Ihnen ihre Ethereum-Adresse zu geben. Auf der anderen Seite, wenn Sie das Passwort irgendwo posten wollen, wo Leute es nachschlagen können, ohne Sie kontaktieren zu müssen, dann sind sie nicht wirklich von Ihnen "autorisiert".
Es braucht einige Zeit, um sich an die Art und Weise zu gewöhnen, wie Ethereum verwendet werden soll. Es wird die Art und Weise verändern, wie Sie bestimmte Probleme angehen.
Können Sie mir sagen, wie ich die Vertragswerte überprüfen kann? Ich habe gerade gelesen, dass jeder es sehen kann, aber nicht weiß, wie. Danke schön.
Möglicherweise etwas zu viele Informationen, aber ... ethereum.stackexchange.com/questions/765/… . Da Miner alle Transaktionen verifizieren, die den Vertragsstatus ändern würden, kann man mit Sicherheit sagen, dass diese Transaktionen von allen Verifizierern bezeugt werden. Transaktionsnutzlasten sind für alle sichtbar. Jacobs Idee, Hashes zu verwenden, ist realisierbar und für einige Anwendungsfälle geeignet. In den meisten Fällen ist es besser, die natürliche Methode von Ethereum zur Authentifizierung zu verwenden. Ich hoffe es hilft.
Wenn ich es richtig verstanden habe, werden eigentlich nicht alle Daten aus dem Vertrag geöffnet, aber nur Verifizierer können wirklich alle Daten "sehen", habe ich recht? Also kann nicht jeder Passant wirklich Vertragsdaten bekommen, nur indem er die Vertragsadresse kennt, oder?
Nun ... jeder kann sehen, weil jeder ein Prüfer sein kann. Hauptmitnahme: keine Geheimnisse in der Kette oder verschlüsseln.
Ich würde vorschlagen, eine Genehmigungszuordnung mit einem Wahr/Falsch-Wert zu speichern, und sobald jemand dem Standardwert „Falsch“ beitritt, genehmigen Sie ihn separat als wahr und verwenden diese Tabelle zur Authentifizierung. Beispielsweise require(approved[msg.sender,true);benötigen Sie möglicherweise Methoden zum Genehmigen, Auflisten und Aussetzen dieser Liste. und machen Sie es vielleicht zu einer Struktur, um Dinge wie Namen oder andere Informationen hinzuzufügen, um das Mitglied zu identifizieren,

Wenn ich Ihre Anforderungen richtig verstehe, können Sie den folgenden Ansatz implementieren:

  1. Generieren Sie Passwörter für alle eingeladenen Benutzer und versenden Sie diese.
  2. Speichern Sie in Ihrem Vertrag Hash-Werte dieser Passwörter mit dem keccak256- Algorithmus (Sie können dies mit der Javascript-Bibliothek tun ). Denken Sie daran, sie außerhalb der Kette zu hashen und die endgültigen Werte an den Vertrag zu senden.
  3. Bitten Sie eingeladene Benutzer, das erhaltene Passwort preiszugeben. Hashen Sie es on-chain mit der Solidity-Methode keccak256() und wenn die Hashes gleich sind, erlauben Sie einem Benutzer, Ihrem Vertrag beizutreten.
Wird das On-Chain-Hashing des Passworts in Schritt 3 das Passwort nicht preisgeben?
Ja, es wird das Passwort preisgeben. Ich habe das Wort sogar benutzt reveal, um Verwirrung zu vermeiden. Nach der Erklärung des Frageautors: "Meinem Vertrag nur mit dem Passwort beitreten" können Sie meine Lösung als Ticket zum Beitritt zu einem Vertrag ansehen, der während der revealPhase validiert wird.
Um einen guten Hash-Wert zu erstellen, muss ich neben dem Passwort einige "Infos" (Blocknummer oder so) verwenden. Und wenn ich nach dem Verschlüsseln des empfangenen Passworts den richtigen Hash-Wert erhalten möchte, muss ich diese „Info“ speichern. Aber wie ich sehe, ist es unmöglich.
Wenn Sie allgemeine Werte wie Wörter oder kleine Zahlen hashen, benötigen Sie ein zusätzliches Stück Zufälligkeit, das als Salz bezeichnet wird , um sich vor Reverse-Hashing zu schützen. Aus diesem Grund gibt es häufig einen Anwendungsfall, in dem die Blocknummer zum Hash-Wert hinzugefügt wird. Aber wenn Sie bereits lange genug zufällige Passwörter generieren, nehme ich nicht an, dass externes Salz benötigt wird.
danke, das macht sinn. Wenn es keinen besseren Weg gibt, muss man so etwas tun.

Speichern Sie Passwörter nicht wie empfohlen, verwenden Sie stattdessen msg.sender zur Authentifizierung

Aber was ist, wenn ich einen neuen Benutzer brauche, um meinem Vertrag nur mit Passwort beizutreten? Damit nicht jeder mitmachen konnte, nur wer das Passwort von mir bekommen hat. Und was ist mit anderen Informationen zu tun, zum Beispiel einigen Dokumenteninformationen wie Passinformationen usw.

Wie Jakub betonte, können Sie keccak256 verwenden, um geheime Passwörter zu speichern und zu überprüfen. Zwei Probleme bei dieser Methode:

  1. Durch die Eingabe des Klartext-Passworts während des Zugriffs wird es jedem angezeigt, der den Pool für ausstehende Transaktionen überwacht. Ein Angreifer kann dann gegen Ihren Benutzer antreten und das Passwort verwenden, indem er eine entsprechende Transaktion generiert und einen höheren Gaspreis angibt, der früher ausgeführt wird als der Ihres legitimen Benutzers.

  2. Sobald das Passwort verwendet wurde, ist es nicht mehr geheim.

Es gibt nichts, was Sie tun können, um 1. abzuschwächen, abgesehen davon, dass Sie bei der Verwendung des Passworts zunächst einen unerschwinglich hohen Benzinpreis verwenden.

Um 2. abzumildern, können Sie den Benutzer auffordern, einen neuen Passwort-Hash zu generieren und anzugeben, der zusammen mit dem Passwort gesendet werden muss, um ein neues One-Use-Passwort für das nächste Mal zu erstellen. Spülen wiederholen.

Wenn ich deine Frage richtig verstanden habe,

Das Vertragsbereitstellungskonto sollte die zulässigen Benutzer lange vor oder nach der Bereitstellung kennen.

Für Ihren Fall müssen Sie alle Benutzer kennen, während die Bereitstellung eingeführt wird.

Eine andere Option besteht darin, jedem zu erlauben, RequestRegister anzufordern, einen eventTrigger davon zu haben, Ihre einmalige Authentifizierungslogik auszuführen und die Absenderadresse in der Liste der zugelassenen Benutzer zu registrieren.

Damit sind weitere Nachverfolgungen von erlaubten Benutzern einfach und jederzeit auch Benutzerhinzufügung möglich.