Ako funguje decentralizovaný messenger na blockchaine?

Začiatkom roka 2017 sme začali vytvárať messenger na blockchaine [meno a odkaz sú v profile] diskutovaním o výhodách oproti klasickým P2P messengerom.

preč 2.5 rok a mohli sme potvrdiť náš koncept: aplikácie messenger sú teraz dostupné pre iOS, Web PWA, Windows, GNU/Linux, Mac OS a Android.

Dnes vám povieme, ako funguje blockchain messenger a ako môžu klientske aplikácie pracovať s jeho API.
Ako funguje decentralizovaný messenger na blockchaine?

Chceli sme, aby blockchain vyriešil otázky bezpečnosti a súkromia klasických P2P messengerov:

  • Jedným kliknutím vytvoríte účet – žiadne telefóny alebo e-maily, žiadny prístup k adresárom alebo geolokáciám.
  • Účastníci rozhovoru nikdy nevytvoria priame spojenie, všetka komunikácia prebieha prostredníctvom distribuovaného systému uzlov. IP adresy používateľov nie sú navzájom prístupné.
  • Všetky správy sú šifrované End-to-End krivka25519xsalsa20poly1305. Zdá sa, že to nikoho neprekvapí, no náš zdrojový kód je otvorený.
  • MITM útok je vylúčený – každá správa je transakcia a je podpísaná Ed25519 EdDSA.
  • Správa končí vo vlastnom bloku. Dôslednosť a timestamp Nemôžete opraviť bloky, a teda poradie správ.
  • „To som nepovedal“ nebude fungovať so správami na blockchaine.
  • Neexistuje žiadna centrálna štruktúra, ktorá by kontrolovala „pravosť“ správy. Robí to distribuovaný systém uzlov založený na konsenze a je vo vlastníctve používateľov.
  • Nemožnosť cenzúry – účty sa nedajú zablokovať a správy sa nedajú vymazať.
  • Blockchain 2FA je alternatívou k pekelnej 2FA cez SMS, zničil veľa zdravia.
  • Možnosť získať všetky konverzácie z akéhokoľvek zariadenia a kedykoľvek znamená, že konverzácie nemusíte vôbec ukladať lokálne.
  • Potvrdenie o doručení správy. Nie do zariadenia používateľa, ale do siete. V podstate ide o potvrdenie schopnosti príjemcu prečítať si vašu správu. Toto je užitočná funkcia na odosielanie kritických upozornení.

Medzi výhody blockchainu patrí aj úzka integrácia s kryptomenami Ethereum, Dogecoin, Lisk, Dash, Bitcoin (tento ešte prebieha) a možnosť posielať tokeny v chatoch. Dokonca sme vyrobili vstavaný krypto výmenník.

A potom – ako to celé funguje.

Správa je transakcia

Každý je už zvyknutý na to, že transakcie v blockchaine prenášajú tokeny (coiny) od jedného používateľa k druhému. Ako Bitcoin. Vytvorili sme špeciálny typ transakcie na prenos správ.

Ak chcete odoslať správu cez messenger na blockchaine, musíte prejsť niekoľkými krokmi:

  1. Šifrovať text správy
  2. Vložte šifrovaný text do transakcie
  3. Podpíšte transakciu
  4. Odošlite transakciu do ľubovoľného sieťového uzla
  5. Distribuovaný systém uzlov určuje „autentickosť“ správy
  6. Ak je všetko v poriadku, transakcia so správou sa zaradí do ďalšieho bloku
  7. Príjemca získa transakciu správy a dešifruje ju

Kroky 1–3 a 7 sa vykonávajú lokálne na klientovi a kroky 5–6 sa vykonávajú na hostiteľoch.

Šifrovanie správ

Správa je zašifrovaná súkromným kľúčom odosielateľa a verejným kľúčom príjemcu. Vezmeme verejný kľúč zo siete, ale na tento účel musí byť účet príjemcu inicializovaný, to znamená, že musí mať aspoň jednu transakciu. Môžete použiť požiadavku REST GET /api/accounts/getPublicKey?address={ADAMANT address}a pri načítavaní rozhovorov už budú k dispozícii verejné kľúče účastníkov rozhovoru.

Ako funguje decentralizovaný messenger na blockchaine?

Messenger šifruje správy pomocou algoritmu curve25519xsalsa20poly1305 (NaCl box). Keďže účet obsahuje kľúče Ed25519, na vytvorenie krabice musia byť kľúče najprv prevedené na Curve25519 Diffie-Hellman.

Tu je príklad v jazyku JavaScript:

/**
 * Encodes a text message for sending to ADM
 * @param {string} msg message to encode
 * @param {*} recipientPublicKey recipient's public key
 * @param {*} privateKey our private key
 * @returns {{message: string, nonce: string}}
 */
adamant.encodeMessage = function (msg, recipientPublicKey, privateKey) {
  const nonce = Buffer.allocUnsafe(24)
  sodium.randombytes(nonce)

  if (typeof recipientPublicKey === 'string') {
    recipientPublicKey = hexToBytes(recipientPublicKey)
  }

  const plainText = Buffer.from(msg)
  const DHPublicKey = ed2curve.convertPublicKey(recipientPublicKey)
  const DHSecretKey = ed2curve.convertSecretKey(privateKey)

  const encrypted = nacl.box(plainText, nonce, DHPublicKey, DHSecretKey)

  return {
    message: bytesToHex(encrypted),
    nonce: bytesToHex(nonce)
  }
}

Vytvorenie transakcie so správou

Transakcia má nasledujúcu všeobecnú štruktúru:

{
  "id": "15161295239237781653",
  "height": 7585271,
  "blockId": "16391508373936326027",
  "type": 8,
  "block_timestamp": 45182260,
  "timestamp": 45182254,
  "senderPublicKey": "bd39cc708499ae91b937083463fce5e0668c2b37e78df28f69d132fce51d49ed",
  "senderId": "U16023712506749300952",
  "recipientId": "U17653312780572073341",
  "recipientPublicKey": "23d27f616e304ef2046a60b762683b8dabebe0d8fc26e5ecdb1d5f3d291dbe21",
  "amount": 204921300000000,
  "fee": 50000000,
  "signature": "3c8e551f60fedb81e52835c69e8b158eb1b8b3c89a04d3df5adc0d99017ffbcb06a7b16ad76d519f80df019c930960317a67e8d18ab1e85e575c9470000cf607",
  "signatures": [],
  "confirmations": 3660548,
  "asset": {}
}

Pre transakciu správ je najdôležitejšia vec asset - do objektu musíte umiestniť správu chat so štruktúrou:

  • message - uložiť zašifrovanú správu
  • own_message - nič
  • type — typ správy

Správy sú tiež rozdelené do typov. V podstate parameter type vám povie, ako rozumieť message. Môžete poslať len textovú správu, alebo môžete poslať objekt so zaujímavými vecami vo vnútri - napríklad takto messenger uskutočňuje prevody kryptomien v chatoch.

V dôsledku toho vytvoríme transakciu:

{
  "transaction": {
    "type": 8,
    "amount": 0,
    "senderId": "U12499126640447739963",
    "senderPublicKey": "e9cafb1e7b403c4cf247c94f73ee4cada367fcc130cb3888219a0ba0633230b6",
    "asset": {
      "chat": {
        "message": "cb682accceef92d7cddaaddb787d1184ab5428",
        "own_message": "e7d8f90ddf7d70efe359c3e4ecfb5ed3802297b248eacbd6",
        "type": 1
      }
    },
    "recipientId": "U15677078342684640219",
    "timestamp": 63228087,
    "signature": "тут будет подпись"
  }
}

Podpis transakcie

Transakcia je podpísaná, aby sa zabezpečilo, že všetci budú mať istotu v pravosť odosielateľa a príjemcu, čas odoslania a obsah správy. Digitálny podpis umožňuje overiť pravosť transakcie pomocou verejného kľúča – na to nie je potrebný súkromný kľúč.

Samotný podpis sa však vykonáva pomocou súkromného kľúča:

Ako funguje decentralizovaný messenger na blockchaine?

Diagram ukazuje, že najprv transakciu zahašujeme pomocou SHA-256 a potom ju podpíšeme Ed25519 EdDSA a získajte podpis signaturea ID transakcie je súčasťou hash SHA-256.

Príklad implementácie:

1 — Vytvorte dátový blok vrátane správy

/**
 * Calls `getBytes` based on transaction type
 * @see privateTypes
 * @implements {ByteBuffer}
 * @param {transaction} trs
 * @param {boolean} skipSignature
 * @param {boolean} skipSecondSignature
 * @return {!Array} Contents as an ArrayBuffer.
 * @throws {error} If buffer fails.
 */

adamant.getBytes = function (transaction) {

  ...

  switch (transaction.type) {
    case constants.Transactions.SEND:
      break
    case constants.Transactions.CHAT_MESSAGE:
      assetBytes = this.chatGetBytes(transaction)
      assetSize = assetBytes.length
      break

…

    default:
      alert('Not supported yet')
  }

  var bb = new ByteBuffer(1 + 4 + 32 + 8 + 8 + 64 + 64 + assetSize, true)

  bb.writeByte(transaction.type)
  bb.writeInt(transaction.timestamp)

  ...

  bb.flip()
  var arrayBuffer = new Uint8Array(bb.toArrayBuffer())
  var buffer = []

  for (var i = 0; i < arrayBuffer.length; i++) {
    buffer[i] = arrayBuffer[i]
  }

  return Buffer.from(buffer)
}

2 - Spočítajte SHA-256 z bloku údajov

/**
 * Creates hash based on transaction bytes.
 * @implements {getBytes}
 * @implements {crypto.createHash}
 * @param {transaction} trs
 * @return {hash} sha256 crypto hash
 */
adamant.getHash = function (trs) {
  return crypto.createHash('sha256').update(this.getBytes(trs)).digest()
}

3 — Podpíšte transakciu

adamant.transactionSign = function (trs, keypair) {
  var hash = this.getHash(trs)
  return this.sign(hash, keypair).toString('hex')
}

/**
 * Creates a signature based on a hash and a keypair.
 * @implements {sodium}
 * @param {hash} hash
 * @param {keypair} keypair
 * @return {signature} signature
 */
adamant.sign = function (hash, keypair) {
  return sodium.crypto_sign_detached(hash, Buffer.from(keypair.privateKey, 'hex'))
}

Odoslanie transakcie so správou do sieťového uzla

Keďže sieť je decentralizovaná, postačí ktorýkoľvek z uzlov s otvoreným API. Vytvorenie požiadavky POST na koncový bod api/transactions:

curl 'api/transactions' -X POST 
  -d 'TX_DATA'

Ako odpoveď dostaneme ID transakcie typu

{
    "success": true,
    "nodeTimestamp": 63228852,
    "transactionId": "6146865104403680934"
}

Overenie transakcie

Distribuovaný systém uzlov, založený na konsenze, určuje „autentickosť“ transakčnej správy. Od koho a komu, kedy, či bola správa nahradená inou a či bol správne uvedený čas odoslania. Toto je veľmi dôležitá výhoda blockchainu – neexistuje žiadna centrálna štruktúra, ktorá by bola zodpovedná za overenie, a postupnosť správ a ich obsah nemožno sfalšovať.

Najprv jeden uzol skontroluje presnosť a potom to pošle ostatným – ak väčšina povie, že je všetko v poriadku, transakcia sa zaradí do ďalšieho bloku reťazca – ide o konsenzus.

Ako funguje decentralizovaný messenger na blockchaine?

Časť kódu uzla, ktorá je zodpovedná za kontroly, si môžete pozrieť na GitHub - validator.js и over.js. Áno, uzol beží na Node.js.

Vrátane transakcie so správou v bloku

Ak sa dosiahne konsenzus, transakcia s našou správou bude zaradená do ďalšieho bloku spolu s ostatnými platnými transakciami.

Bloky majú prísnu postupnosť a každý nasledujúci blok je vytvorený na základe hashov predchádzajúcich blokov.

Ako funguje decentralizovaný messenger na blockchaine?

Ide o to, že naša správa je tiež zahrnutá v tejto sekvencii a nedá sa „preusporiadať“. Ak niekoľko správ spadá do bloku, ich poradie bude určené podľa timestamp správ.

Čítanie správ

Aplikácia messenger získava transakcie z blockchainu, ktoré sa odosielajú príjemcovi. Na tento účel sme urobili konečný bod api/chatrooms.

Všetky transakcie sú dostupné pre každého – môžete prijímať zašifrované správy. Ale iba príjemca môže dešifrovať pomocou svojho súkromného kľúča a verejného kľúča odosielateľa:

**
 * Decodes the incoming message
 * @param {any} msg encoded message
 * @param {string} senderPublicKey sender public key
 * @param {string} privateKey our private key
 * @param {any} nonce nonce
 * @returns {string}
 */
adamant.decodeMessage = function (msg, senderPublicKey, privateKey, nonce) {
  if (typeof msg === 'string') {
    msg = hexToBytes(msg)
  }

  if (typeof nonce === 'string') {
    nonce = hexToBytes(nonce)
  }

  if (typeof senderPublicKey === 'string') {
    senderPublicKey = hexToBytes(senderPublicKey)
  }

  if (typeof privateKey === 'string') {
    privateKey = hexToBytes(privateKey)
  }

  const DHPublicKey = ed2curve.convertPublicKey(senderPublicKey)
  const DHSecretKey = ed2curve.convertSecretKey(privateKey)
  const decrypted = nacl.box.open(msg, nonce, DHPublicKey, DHSecretKey)

  return decrypted ? decode(decrypted) : ''
}

A čo ešte?

Keďže správy sa doručujú týmto spôsobom približne za 5 sekúnd – to je čas, kedy sa objaví nový sieťový blok – prišli sme so spojením soketu klient-uzl a uzol. Keď uzol prijme novú transakciu, skontroluje jej platnosť a odošle ju ďalším uzlom. Transakcia je dostupná klientom messengeru ešte predtým, ako dôjde ku konsenzu a začleneniu do bloku. Týmto spôsobom budeme doručovať správy okamžite, rovnako ako bežní instant messenger.

Na uloženie adresára sme vytvorili KVS - Key-Value Storage - to je ďalší typ transakcie, pri ktorej asset nie je to NaCl-box, ktorý je zašifrovaný, ale NaCl-tajná schránka. Takto messenger ukladá ďalšie údaje.

Prenosy súborov/obrázkov a skupinové rozhovory si stále vyžadujú veľa práce. Samozrejme, vo formáte „blunder-and-blunder“ sa to dá rýchlo „pokaziť“, ale chceme zachovať rovnakú úroveň súkromia.

Áno, stále je na čom pracovať – v ideálnom prípade skutočné súkromie predpokladá, že používatelia sa nebudú pripájať k uzlom verejnej siete, ale vytvoria si svoje vlastné. Čo myslíte, aké percento používateľov to robí? Správne, 0. Tento problém sa nám podarilo čiastočne vyriešiť pomocou Tor verzie messengeru.

Dokázali sme, že messenger na blockchaine môže existovať. Predtým to bol iba jeden pokus v roku 2012 - bitová správa, ktorá zlyhala pre dlhé časy doručovania správ, zaťaženie procesora a nedostatok mobilných aplikácií.

A skepticizmus je spôsobený tým, že poslovia na blockchaine predbehli dobu – ľudia nie sú pripravení prevziať zodpovednosť za svoj účet, vlastniť osobné informácie zatiaľ nie je trendom a technológie neumožňujú vysoké rýchlosti na blockchaine. Ďalej sa objavia ďalšie technologické analógy nášho projektu. Uvidíte.

Zdroj: hab.com

Pridať komentár