Öffentliche Schlüssel von Besitzer und Absender eines Smart Contracts

Ich bin ziemlich neu bei Ethereum. Ich würde gerne wissen, ob es möglich ist, einen Vertrag zu schreiben, in dem ich den Owneröffentlichen Schlüssel und den öffentlichen Schlüssel des Absenders kennen kann.

Aus Neugier, warum brauchen Sie statt der Adresse den öffentlichen Schlüssel im Vertrag?
@NickJohnson Wollte einige Daten mit dem öffentlichen Schlüssel verschlüsseln und an den Absender senden.
Sie sind sich bewusst, dass die unverschlüsselten Daten in der Blockchain für jeden sichtbar sind, der nachsehen möchte?
@NickJohnson Ja. Also wollte ich eine Transaktion mit der mit dem öffentlichen Schlüssel verschlüsselten Blockchain senden, damit andere sie nicht lesen können.
Das wird jedoch nicht helfen - jeder kann Ihre Transaktion wiederholen und die Daten sehen, bevor sie verschlüsselt wurden.
@NickJohnson Was ist, wenn der Eigentümer nur weiß, welche Daten verschlüsselt werden sollen? Wenn der Absender eine Transaktion sendet und vom Eigentümer empfangen wird. er wird die Daten verschlüsseln und in die Blockchain aufnehmen.
Wenn dies außerhalb der Blockchain erfolgt, benötigen Sie keinen Vertrag, der den privaten Schlüssel eines Kontos erhalten kann: Sie können ihn selbst aus jeder von diesem Konto erstellten Transaktion erhalten.

Antworten (4)

Dies ist nicht direkt möglich: Der öffentliche Schlüssel steht dem Vertrag nicht direkt zur Verfügung. Der Vertrag enthält nur die Adresse des Absenders, die aus dessen öffentlichem Schlüssel abgeleitet wird.

Es ist jedoch möglich, dass ein Vertrag die Ableitung auf die andere Weise durchführt. Wenn Sie ihm also einen öffentlichen Schlüssel als Parameter übergeben, kann er herausfinden, welcher Adresse er entspricht.

Obwohl der Vertrag den öffentlichen Schlüssel nicht sehen kann, ist es technisch möglich, ihn von der Blockchain und/oder dem Netzwerk mit Code abzurufen, der außerhalb des Vertrages läuft, vorausgesetzt, die Adresse wurde tatsächlich mindestens einmal verwendet. Dies ist möglich, weil jedes Mal, wenn Sie eine Transaktion senden, die Überprüfung der Signatur beinhaltet, dass zuerst der öffentliche Schlüssel aus der Signatur wiederhergestellt wird, dann die Adresse berechnet und auf Übereinstimmung überprüft wird.

Eine Sache, die Sie (oder jemand anderes) tun könnten, wäre also, einen Verzeichnisvertrag abzuschließen, der eine Liste von Adressen mit öffentlichen Schlüsseln führt, und einen Bot auszuführen, um ihn nach fehlenden Adressen abzufragen, den öffentlichen Schlüssel aus der Blockchain wiederherzustellen und ihn zu senden zum Verzeichnisvertrag.

Wenn Sie den Bot nicht selbst ausführen möchten, können Sie den Verzeichnisvertrag ändern, um eine Prämie für jeden fehlenden öffentlichen Schlüssel zu verwalten. Ihr Vertrag würde also immer dann eine kleine Menge ETH an den Verzeichnisvertrag senden, wenn er einen öffentlichen Schlüssel wollte, und eine unbekannte Person im Internet würde den öffentlichen Schlüssel suchen, ihn an den Verzeichnisvertrag senden und die Prämie einfordern.

Ich sehe diese Art von Frage, die an vielen verschiedenen Stellen auftaucht, und sie wird (leider) oft mit „das brauchst du nicht“ oder „warum solltest du das wollen“ beantwortet.

Wenn es um Blockchain geht, ist diese Art der Antwort richtig, vorausgesetzt, dass die gesamte „Kommunikation“ durch Senden einer signierten Transaktion an die Blockchain erfolgt. Hier ist die Kenntnis des öffentlichen Schlüssels meist nutzlos.

Jedenfalls, wenn man Blockchain (sprich „Ethereum“) als verteiltes, öffentliches, überprüfbares Verzeichnis von Aufzeichnungen (und Zuständen von Smart Contracts für diese Angelegenheit) und nicht als Grundlage für alle Daten einer App/eines Dienstes sieht, stellt sich die Frage plötzlich sehr des Sinns.

Ein Szenario könnte sein, dass sich zwei Kommunikationspartner auf Geräten außerhalb der Kette befinden (Server, Mobiltelefone, Laptops, ...). Beide haben ein Schlüsselpaar, das zur Identifizierung und Verschlüsselung/Entschlüsselung/Signierung verwendet wird. Das Ledger würde dann beide Benutzeradressen (Teil der Hashes der öffentlichen Schlüssel) registrieren, die dann als (nachweisbare) Identifikatoren verwendet werden. Die Kommunikation würde dann komplett Off-Chain, also direkt zwischen den Geräten der beiden Nutzer stattfinden.

Wenn Benutzer A nun eine signierte Nachricht von Benutzer B erhalten hat, kann A leicht überprüfen, dass die Nachricht nicht manipuliert wurde und tatsächlich vom Besitzer des privaten Schlüssels stammt, der mit der Adresse von A verknüpft ist. (A würde den öffentlichen Schlüssel von B ableiten aus der Signatur der Nachricht, berechne daraus die Adresse und verifiziere, dass es die tatsächliche Adresse von B ist).

Wie auch immer, wenn A und B noch keinen Kontakt hatten und A eine VERSCHLÜSSELTE Nachricht an B senden möchte, gibt es für A keine Möglichkeit, den öffentlichen Schlüssel von B zu erfahren, indem er einfach die Adresse von B kennt.

Benutzer müssen also irgendwo eine Zuordnung ihrer Adressen zu ihren öffentlichen Schlüsseln veröffentlichen. Dies ist im Grunde (ein Teil) der Idee hinter SSI (DIDs und DID-Dokumente).

Nun, davon abgesehen, gibt es einige Möglichkeiten, dies zu erreichen:

  1. Erfordert teilweise, dass jeder Benutzer eine digitale Signatur erstellt, die öffentlich verfügbar und nur von der Adresse des Benutzers aus erkennbar ist. Da wir von EC-Krypto sprechen, kann man den öffentlichen Schlüssel von dieser Signatur ableiten. Eine Möglichkeit, dies zu tun, ohne irgendwo eine bestimmte Registrierung zu haben, wäre, jeden Benutzer auf irgendeine Weise eine Transaktion mit Ethereum durchführen zu lassen. Von hier aus können Sie Transaktionen von dieser Adresse senden/signieren lassen (siehe für ein dummes zufälliges Beispiel https://etherscan.io/address/0x39ec1d8f3d431770a8c79b33ead5a2e9e3c02d25 ) und von dort Signatur und öffentlichen Schlüssel abrufen.

  2. Erstellen Sie eine öffentliche Registrierung mit einer Zuordnung von Adresse zu öffentlichem Schlüssel. Kann entweder ein intelligenter Vertrag mit einer Zuordnung addresszu stringoder eine DID-Registrierung sein, die mit (möglicherweise Off-Chain-) DID-Dokumenten verknüpft ist. Siehe zum Beispiel ERC1056 von uPort.

Um direkt einen MWE für Option 2 vorzuschlagen, könnte man etwa so vorgehen:

contract registry {
  mapping (address => string) private keys;
  
  function getKey(address a) public view returns (string) {
    return keys[a];
  }

  function setKey(string key) public returns (address) {
    address a = address(keccak256(key));
    keys[a] = key;
    return a;
  }
}

EDIT: ein tatsächlich funktionierendes Beispiel zusammengeschlagen:

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.4;

contract KeyRegistry
{
    mapping (address => bytes) private keys;
    
    function getKey(address a) public view returns (bytes)
    {
        if(keys[a] == 0x0)
            revert("Error: Unknown address");
            
        return keys[a];
    }
    
    function setKey(bytes key) public returns (address)
    {
        if(key.length == 0)
            revert("Error: Key cant be empty");
        
        address a = address(uint160(bytes20(key)));
        
        if(a != msg.sender)
            revert("Error: Only the owner of a key can register this key");
        
        if(keys[a] != 0)
            revert("Error: Key is already registered");
        
        keys[a] = key;
        
        return a;
    }
}

Es scheint, als würden Sie versuchen, eine Art verschlüsseltes Messaging-Dapp zu erstellen. Ziemlich cool.

Sie könnten eine Benutzerregistrierung erstellen und die Benutzer für die DAPP "registrieren" lassen, indem Sie ihren eigenen öffentlichen Schlüssel sowie den Schlüsseltyp bereitstellen. Rufen Sie dann Off-Chain in der JS-Schicht diese Benutzermetadaten ab und führen Sie die teuren Verschlüsselungsberechnungen durch und speichern Sie dann das Produkt der Verschlüsselung in einer Nachrichtenzuordnung.

Sie könnten also so etwas tun

struct User{
  string pubKey;
  string keyType;
}

struct Message{
  string body;
}

mapping(address=>User) public users;
mapping(bytes32=>Message) public msgs;

Verwenden Sie eine eindeutige Kennung für die Nachrichtenzuordnung

Für die Solidity -Vertragssprache:
Immer wenn Sie eine Transaktion an einen Vertrag senden

  1. eine Funktion aufrufen,
  2. ETH zum Vertrag zu übertragen (hier nutzt man eine anonyme Fallback-Funktionfunction() {...}

Sie haben Zugriff auf ein msgObjekt, das den öffentlichen Schlüssel des Absenders enthält: msg.sender.
Dies gilt auch für Ihren Konstruktor, bei dem der Absender der Eigentümer/Ersteller des Vertrags ist.

kofier ist es der public keyoder der addressdes User.
Ich sehe, Sie wollen den öffentlichen Schlüssel, da die Adresse ein Hash davon ist, haben Sie Recht, es ist nicht dasselbe. Keine Möglichkeit, den öffentlichen Schlüssel direkt zu kennen, AFAIK.