Sådan sikres beskeder på EOS

En blockchain er en distribueret hovedbog, og hver blok af data er offentligt tilgængelig for alle at se. Du spekulerer måske på, hvad hvis jeg vil kryptere meddelelser på blockchain, specifikt på EOS?

Sådan fungerer beskyttelse af beskeder på en blockchain

Vi kan indarbejde NuCypher. NuCypher hjælper dApp-udviklere med at gemme, dele og administrere private data om offentlige blockchains med decentral proxy-kryptering som en tjeneste.

Sådan fungerer det.

  1. Alice har følsomme data, som hun ønsker at kunne delegere adgang til.
  2. Alice krypterer sine data vha. Sin egen offentlige nøgle og gemmer dem i skyen eller decentraliseret opbevaring.
  3. Alice delegerer adgang til Bob. Dataene gendannes igen til Bobs nøgle i lagring.
  4. Bob downloader dataene og dekrypterer dem med sin private nøgle.

Sikring af en meddelelse på EOS

Vi starter med scenariet, hvor Alice og Bob begge har adgang til den private nøgle, og Alice ønsker at sende følsomme data til Bob, og udnytte pyUmbral, som er NuCypher's referenceimplementering af Umbral (split-key tærskel-proxy-re-kryptering).

Lad os først opbygge en smart kontrakt med en meddelelseskø på EOS.

Det konstruerer en tabel kaldet meddelelser, der indeholder uint64_t msg_id, kontonavn fra, kontonavn til, streng chiffertekst og strengkapsel. msg_id er den primære nøgle.

Det giver to handlinger: sendmsg og deletemsg. sendmsg kræver kontonavn fra og til, msg_id, ciffertext og kapsel. Ciphertext er den krypterede meddelelse, og kapsel er konceptet i Umbral, der genereres ved hjælp af pyUmbral. sletter grundlæggende en msg_id, verificerer det givne toaccount_navn og sletter derefter posten.

klasse kø: offentlig eosio :: kontrakt {
offentlig:
        ved hjælp af kontrakt :: kontrakt;
// @ abi handling
        void sendmsg (kontonavn fra, kontonavn til, uint64_t msg_id, const std :: streng & chiffertekst, const std :: streng & kapsel) {
            kræve_auth (fra);
            meddelelser_index beskeder (_self, _self);
            auto itr = meddelelser.find (msg_id);
            if (itr! = meddelelser.end ()) {
                std :: string error = "msg_id findes allerede:" + std :: to_string (msg_id);
                eosio_assert (falsk, error.c_str ());
}
            messages.emplace (fra, [&] (auto & msg) {
                msg.msg_id = msg_id;
                msg.from = fra;
                msg.to = til;
                msg.ciphertext = ciphertext;
                msg.capsule = kapsel;
            });
}
// @abi handling
        void deletemsg (kontonavn til, uint64_t msg_id) {
            kræve_auth (til);
            meddelelser_index beskeder (_self, _self);
            auto itr = meddelelser.find (msg_id);
            if (itr == meddelelser.end ()) {
                std :: string error = "msg_id findes ikke:" + std :: to_string (msg_id);
                eosio_assert (falsk, error.c_str ());
            }
            
            hvis (itr-> til! = til) {
                std :: string error = "Modtager ikke korrekt:" + eosio :: navn {itr-> til} .to_string ();
                eosio_assert (falsk, error.c_str ());
            }
          
            messages.erase (ITR);
         }
privat:
        // @ abi-tabelmeddelelser i64
        strukturbeskeder {
            uint64_t msg_id;
            kontonavn fra;
            kontonavn til;
            std :: streng ciphertext;
            std :: streng kapsel;
uint64_t primary_key () const {return msg_id;}
        };
        
        typedef eosio :: multi_index  meddelelser_index;
};
EOSIO_ABI (kø, (sendmsg) (deletemsg))

Kompilér det:

eosiocpp -o que.wast queue.cpp
eosiocpp -g kø.abi kø.cpp

Opret en konto for at uploade den smarte kontrakt:

$ cleos Opret konto eosio kø EOS5aEqZf22dfThTR8GGMnD8oFvsyzssQnhawNwPzfPv4fwDWhf7H
udført transaktion: a767af2c66857 ... 200 bytes 3309 os
# eosio <= eosio :: newaccount {"creator": "eosio", "name": "kø", "ejer": {"tærskel": 1, "keys": [{"key": "EOS5aEqZf22dfThTR8GGMnD8oFv .. .
$ cleos indstiller kontraktkø ../queue
Læser WAST / WASM fra ../ kø / kø.wasme ...
Brug af allerede samlet WASM ...
Forlagskontrakt ...
udført transaktion: 38e94741c ... 13824 bytes 9561 os
# eosio <= eosio :: setcode {"account": "kø", "vmtype": 0, "vmversion": 0, "code": "00617ee7e ...
# eosio <= eosio :: setabi {"account": "kø", "abi": "0e656f73696f3a3a6162692f9640675 ...

Opret testkonti alice og bob:

$ cleos Opret konto eosio alice EOS6NU3XEvosgRVEbhrBHrkbYVteW7DDVewhjo9jgiYoSqUZamnZe
udført transaktion: f0c42065f6d9fc ... 200 bytes 243 os
# eosio <= eosio :: newaccount {"creator": "eosio", "name": "alice", "ejer": {"tærskel": 1, "keys": [{"key": "EOS6NU3XEvosgRVEbhrBHrkbYVt .. .
$ cleos Opret konto eosio bob EOS7cX17CZ8V7yFobaVejAN7sMG39iiC5BmFk7b1NB1NNYcrEu1Go
udført transaktion: 51d45916fa252e ... 200 bytes 194 os
# eosio <= eosio :: newaccount {"creator": "eosio", "name": "bob", "ejer": {"tærskel": 1, "keys": [{"key": "EOS7cX17CZ8V7yFobaVejAN7sMG39 .. .

Lad os gå videre og opbygge en klient til at kryptere / dekryptere en meddelelse og interagere med den smarte kontrakt.

  1. Opret en privat nøgle og skriv til en fil.
fra paraplyimportkonfiguration, nøgler
config.set_default_curve (SECP256K1)
private_key = nøgler.UmbralPrivateKey.gen_key ()
f = open ('priv.key', 'wb')
f.write (private_key.to_bytes ())
f.close ()

2. Konstruer en parser

def create_parser ():
    parser = argparse.ArgumentParser (beskrivelse = 'messenger')
    parser.add_argument ('- private-key-file', type = str, dest = 'private_key_file', krævet = False, help = 'Sti til den private key file.')
    parser.add_argument ('- send-msg-id', type = str, dest = 'send_msg_id', krævet = Falsk, hjælp = 'Send en besked, msg_id')
    parser.add_argument ('- send-msg-from', type = str, dest = 'send_msg_from', krævet = Falsk, hjælp = 'Send en meddelelse, hvorfra EOS-konto')
    parser.add_argument ('- send-msg-to', type = str, dest = 'send_msg_to', krævet = Falsk, hjælp = 'Send en besked, til hvilken EOS-konto')
    parser.add_argument ('- send-msg', type = str, dest = 'send_msg', krævet = Falsk, hjælp = 'Besked, der skal sendes')
    parser.add_argument ('- read-msg-to', type = str, dest = 'read_msg_to', krævet = Falsk, hjælp = 'Læs en meddelelse, som EOS-konto til')
    return parser
parser = create_parser ()
args = parser.parse_args (argv)

3. Læs fra privkey-filen.

def read_privkey_file (privkey_file):
    hvis os.path.exists (privkey_file):
        med åben (privkey_file, 'rb') som f:
            prøve:
                privkey = f.read ()
            undtagen undtagelse som e:
                print ("Kan ikke læse: {}". format (e))
                sys.exit (1)
            f.close ()
            return privkey
    andet:
        print ('Kan ikke finde fil: {}'. format (privkey_file))
        sys.exit (1)

3. Krypter en besked, og send den.

def send_msg (private_key_file, msg, send_msg_from, send_msg_to, send_msg_id):
    privkey_bytes = read_privkey_file (private_key_file)
    privkey = nøgler.UmbralPrivateKey.from_bytes (privkey_bytes)
    pubkey = privkey.get_pubkey ()
plaintext = msg.encode ()
    ciphertext, kapsel = pre.encrypt (pubkey, plaintext)
data = '{"fra": "' + send_msg_from + '", "til": "' + send_msg_to + '", "msg_id": "' + send_msg_id + '", "ciphertext": "' + ciphertext.hex () + '"," kapsel ":"' + kapsel.to_bytes (). hex () + '"}'
    subprocess.call (['cleos', 'push', 'action', DEFAULT_ACCOUNT, 'sendmsg', data, '-p', send_msg_from])

3. Læs fra meddelelsestabellen, hvis du matcher read_msg_to, skal du dekryptere en meddelelse og derefter slette den.

def read_and_delete_msg (private_key_file, read_msg_to):
    privkey_bytes = read_privkey_file (private_key_file)
    privkey = nøgler.UmbralPrivateKey.from_bytes (privkey_bytes)
    
    nyttelast = '{"scope": "' + DEFAULT_ACCOUNT + '", "code": "' + DEFAULT_ACCOUNT + '", "table": "' + DEFAULT_TABLE + '", "json": "sand"}'
    respons = forespørgsel.anmodning ("POST", DEFAULT_URL, data = nyttelast)
    
    fundet = falsk
    for msg in response.json () ['rækker']:
        if msg ['to'] == read_msg_to:
            ciphertext = msg ['ciphertext']
            kapsel = msg ['kapsel']
            msg_id = msg ['msg_id']
            fundet = sandt
            pause
hvis fundet:
        capule = pre.Capsule.from_bytes (bytes.fromhex (kapsel), privkey.params)
        cleartext = pre.decrypt (
                          ciphertext = bytes.fromhex (ciphertext),
                          kapsel = kapsel,
                          decrypting_key = privkey)
        print ('Cleartext: {}'. format (cleartext))
print ('Sletning af msg_id: {}'. format (msg_id))
        data = '{"til": "' + read_msg_to + '", "msg_id": "' + str (msg_id) + '"}'
        subprocess.call (['cleos', 'push', 'action', DEFAULT_ACCOUNT, 'deletemsg', data, '-p', read_msg_to])

4. Standardværdier.

DEFAULT_ACCOUNT = 'kø'
DEFAULT_TABLE = 'meddelelser'
DEFAULT_URL = "http://127.0.0.1:8888/v1/chain/get_table_rows"

Lad os pakke dem op og teste!

$ python3 messenger.py - private-key-file priv.key - send-msg-id 1 - send-msg-fra alice - send-msg-to bob - send-msg hej, bob
udført transaktion: dfe17144e105c54d192 ... 392 bytes 648 os
# kø <= kø :: sendmsg {"fra": "alice", "til": "bob", "msg_id": 1, "ciphertext": "8c53a656c9 ...

Kontroller meddelelsestabellen.

$ cleos får tabelkømeddelelser
{
  "rækker": [{
      "msg_id": 1,
      "fra": "alice",
      "til": "bob",
      "ciphertext": "8c8aa24196152b53da35d9fbf9e3c4d8e10f6b7153a656c9921cb440cc69a782c2ba0c2cf2",
      "kapsel": "028c4e8279c0919bdec4ea98b4251f15a74868d2ea7554ab796230af8f88e62cd9031c07e90c6183152e7f7a7d7a7a7a7a7a7a7a7a
    }
  ],
  "mere": falsk
}

Den krypterede meddelelse er der. Lad os derefter læse det.

$ python3 messenger.py - private-key-fil priv.key - read-msg-to bob
Klar tekst: b'hello, bob '
Sletning af msg_id: 1
udført transaktion: 6cdad7694f3fe6c8 ... 112 bytes 566 os
# kø <= kø :: deletemsg {"til": "bob", "msg_id": 1}

Kontroller meddelelsestabellen, meddelelsen er væk.

$ cleos får tabelkømeddelelser
{
  "rækker": [],
  "mere": falsk
}

Således udforskede vi, hvordan man kan sikre beskeder på EOS. Når vi bevæger os fremad, kan vi arbejde med et scenarie, hvor Alice og Bob har deres egne nøgler eller sender til flere brugere.