Paano gumagana ang isang desentralisadong messenger sa blockchain?

Sa simula ng 2017, nagsimula kaming gumawa ng messenger sa blockchain [nasa profile ang pangalan at link] sa pamamagitan ng pagtalakay sa mga pakinabang sa mga klasikong P2P messenger.

wala na 2.5 taon, at nakumpirma namin ang aming konsepto: available na ngayon ang mga messenger application para sa iOS, Web PWA, Windows, GNU/Linux, Mac OS at Android.

Ngayon sasabihin namin sa iyo kung paano gumagana ang blockchain messenger at kung paano gumagana ang mga application ng kliyente sa API nito.
Paano gumagana ang isang desentralisadong messenger sa blockchain?

Nais naming lutasin ng blockchain ang mga isyu sa seguridad at privacy ng mga klasikong P2P messenger:

  • Isang pag-click upang lumikha ng isang account - walang mga telepono o email, walang access sa mga address book o geolocation.
  • Ang mga interlocutor ay hindi kailanman nagtatag ng mga direktang koneksyon; lahat ng komunikasyon ay nagaganap sa pamamagitan ng isang distributed system ng mga node. Ang mga IP address ng mga gumagamit ay hindi naa-access sa isa't isa.
  • Ang lahat ng mga mensahe ay naka-encrypt na End-to-End curve25519xsalsa20poly1305. Mukhang hindi ito magugulat sa sinuman, ngunit bukas ang aming source code.
  • Ang pag-atake ng MITM ay hindi kasama - ang bawat mensahe ay isang transaksyon at nilagdaan ng Ed25519 EdDSA.
  • Ang mensahe ay nagtatapos sa sarili nitong bloke. Consistency at timestamp Hindi mo maaaring ayusin ang mga bloke, at samakatuwid ay ang pagkakasunud-sunod ng mga mensahe.
  • "Hindi ko sinabi na" ay hindi gagana sa mga mensahe sa blockchain.
  • Walang sentral na istraktura na nagsusuri sa "authenticity" ng isang mensahe. Ginagawa ito ng isang distributed system ng mga node batay sa consensus, at ito ay pag-aari ng mga user.
  • Imposibilidad ng censorship - hindi ma-block ang mga account at hindi matatanggal ang mga mensahe.
  • Ang Blockchain 2FA ay isang alternatibo sa mala-impyernong 2FA sa pamamagitan ng SMS, sumira ng maraming kalusugan.
  • Ang kakayahang makuha ang lahat ng iyong mga pag-uusap mula sa anumang device anumang oras ay nangangahulugan na hindi mo na kailangang mag-imbak ng mga pag-uusap nang lokal sa lahat.
  • Pagkumpirma ng paghahatid ng mensahe. Hindi sa device ng user, ngunit sa network. Sa pangkalahatan, ito ay kumpirmasyon ng kakayahan ng tatanggap na basahin ang iyong mensahe. Ito ay isang kapaki-pakinabang na tampok para sa pagpapadala ng mga kritikal na notification.

Kasama rin sa mga benepisyo ng Blockchain ang malapit na pagsasama sa mga cryptocurrencies na Ethereum, Dogecoin, Lisk, Dash, Bitcoin (ito ay kasalukuyang isinasagawa pa) at ang kakayahang magpadala ng mga token sa mga chat. Gumawa pa kami ng built-in na crypto exchanger.

At pagkatapos - kung paano gumagana ang lahat.

Ang mensahe ay isang transaksyon

Ang lahat ay nakasanayan na sa katotohanan na ang mga transaksyon sa blockchain ay naglilipat ng mga token (mga barya) mula sa isang user patungo sa isa pa. Parang Bitcoin. Gumawa kami ng isang espesyal na uri ng transaksyon para sa pagpapadala ng mga mensahe.

Upang magpadala ng mensahe sa isang messenger sa blockchain, kailangan mong dumaan sa ilang hakbang:

  1. I-encrypt ang text ng mensahe
  2. Ilagay ang ciphertext sa isang transaksyon
  3. Pirmahan ang transaksyon
  4. Magpadala ng transaksyon sa anumang network node
  5. Tinutukoy ng isang distributed system ng mga node ang "authenticity" ng isang mensahe
  6. Kung ang lahat ay OK, ang transaksyon na may mensahe ay kasama sa susunod na bloke
  7. Kinukuha ng tatanggap ang transaksyon ng mensahe at nagde-decrypt

Ang mga hakbang 1–3 at 7 ay isinasagawa nang lokal sa kliyente, at ang mga hakbang 5–6 ay isinasagawa sa mga host.

Pag-encrypt ng mensahe

Ang mensahe ay naka-encrypt gamit ang pribadong susi ng nagpadala at ang pampublikong susi ng tatanggap. Kukunin namin ang pampublikong susi mula sa network, ngunit para dito, dapat masimulan ang account ng tatanggap, iyon ay, magkaroon ng kahit isang transaksyon. Maaari kang gumamit ng kahilingan sa REST GET /api/accounts/getPublicKey?address={ADAMANT address}, at kapag naglo-load ng mga chat, magiging available na ang mga pampublikong key ng mga kausap.

Paano gumagana ang isang desentralisadong messenger sa blockchain?

Ini-encrypt ng messenger ang mga mensahe gamit ang curve25519xsalsa20poly1305 algorithm (Kahon ng NaCl). Dahil naglalaman ang account ng mga Ed25519 key, para makabuo ng isang kahon, dapat munang i-convert ang mga key sa Curve25519 Diffie-Hellman.

Narito ang isang halimbawa sa 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)
  }
}

Pagbuo ng isang transaksyon na may mensahe

Ang transaksyon ay may sumusunod na pangkalahatang istraktura:

{
  "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": {}
}

Para sa isang transaksyon sa mensahe, ang pinakamahalagang bagay ay asset - kailangan mong maglagay ng mensahe sa bagay chat may istraktura:

  • message - i-save ang naka-encrypt na mensahe
  • own_message - wala
  • type β€” uri ng mensahe

Ang mga mensahe ay nahahati din sa mga uri. Mahalaga, ang parameter type nagsasabi sa iyo kung paano maunawaan message. Maaari kang magpadala lamang ng isang text, o maaari kang magpadala ng isang bagay na may mga kagiliw-giliw na bagay sa loob - halimbawa, ito ay kung paano gumagawa ang messenger ng mga paglilipat ng cryptocurrency sa mga chat.

Bilang resulta, lumikha kami ng isang transaksyon:

{
  "transaction": {
    "type": 8,
    "amount": 0,
    "senderId": "U12499126640447739963",
    "senderPublicKey": "e9cafb1e7b403c4cf247c94f73ee4cada367fcc130cb3888219a0ba0633230b6",
    "asset": {
      "chat": {
        "message": "cb682accceef92d7cddaaddb787d1184ab5428",
        "own_message": "e7d8f90ddf7d70efe359c3e4ecfb5ed3802297b248eacbd6",
        "type": 1
      }
    },
    "recipientId": "U15677078342684640219",
    "timestamp": 63228087,
    "signature": "Ρ‚ΡƒΡ‚ Π±ΡƒΠ΄Π΅Ρ‚ подпись"
  }
}

Lagda ng transaksyon

Upang matiyak na ang lahat ay tiwala sa pagiging tunay ng nagpadala at tatanggap, ang oras ng pagpapadala at ang nilalaman ng mensahe, ang transaksyon ay nilagdaan. Ang isang digital na lagda ay nagbibigay-daan sa iyo upang i-verify ang pagiging tunay ng isang transaksyon gamit ang isang pampublikong susi - isang pribadong susi ay hindi kailangan para dito.

Ngunit ang pirma mismo ay ginagawa gamit ang pribadong key:

Paano gumagana ang isang desentralisadong messenger sa blockchain?

Ipinapakita ng diagram na hina-hash muna namin ang transaksyon gamit ang SHA-256 at pagkatapos ay lagdaan ito Ed25519 EdDSA at kumuha ng pirma signature, at ang transaction ID ay bahagi ng SHA-256 hash.

Halimbawang pagpapatupad:

1 β€” Bumuo ng data block, kabilang ang isang mensahe

/**
 * 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 - Bilangin ang SHA-256 mula sa data block

/**
 * 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 β€” Lagdaan ang transaksyon

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'))
}

Pagpapadala ng transaksyon na may mensahe sa isang network node

Dahil desentralisado ang network, magagawa ang alinman sa mga node na may bukas na API. Paggawa ng POST na kahilingan sa endpoint api/transactions:

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

Bilang tugon, makakatanggap kami ng transaction ID ng uri

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

Pagpapatunay ng Transaksyon

Tinutukoy ng isang distributed system ng mga node, batay sa consensus, ang "authenticity" ng mensahe ng transaksyon. Mula kanino at kanino, kailan, kung ang mensahe ay pinalitan ng isa pa, at kung ang oras ng pagpapadala ay naipahiwatig nang tama. Ito ay isang napakahalagang bentahe ng blockchain - walang sentral na istraktura na responsable para sa pag-verify, at ang pagkakasunud-sunod ng mga mensahe at ang kanilang nilalaman ay hindi maaaring pekein.

Una, sinusuri ng isang node ang katumpakan, at pagkatapos ay ipapadala ito sa iba - kung sinasabi ng karamihan na maayos ang lahat, ang transaksyon ay isasama sa susunod na bloke ng kadena - ito ay pinagkasunduan.

Paano gumagana ang isang desentralisadong messenger sa blockchain?

Ang bahagi ng node code na responsable para sa mga pagsusuri ay maaaring matingnan sa GitHub - validator.js ΠΈ verify.js. Oo, tumatakbo ang node sa Node.js.

Kabilang ang isang transaksyon na may mensahe sa isang bloke

Kung naabot ang pinagkasunduan, ang transaksyon sa aming mensahe ay isasama sa susunod na bloke kasama ng iba pang wastong transaksyon.

Ang mga bloke ay may mahigpit na pagkakasunud-sunod, at ang bawat kasunod na bloke ay nabuo batay sa mga hash ng nakaraang mga bloke.

Paano gumagana ang isang desentralisadong messenger sa blockchain?

Ang punto ay ang aming mensahe ay kasama rin sa sequence na ito at hindi maaaring "muling ayusin". Kung maraming mensahe ang nahulog sa isang bloke, ang kanilang pagkakasunud-sunod ay matutukoy ng timestamp mga mensahe.

Nagbabasa ng mga mensahe

Kinukuha ng messenger application ang mga transaksyon mula sa blockchain na ipinadala sa tatanggap. Para dito gumawa kami ng endpoint api/chatrooms.

Ang lahat ng mga transaksyon ay magagamit sa lahat - maaari kang makatanggap ng mga naka-encrypt na mensahe. Ngunit ang tatanggap lamang ang makakapag-decrypt gamit ang kanyang pribadong susi at ang pampublikong susi ng nagpadala:

**
 * 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) : ''
}

Ano pa?

Dahil ang mga mensahe ay inihahatid sa ganitong paraan sa loob ng humigit-kumulang 5 segundo - ito ang oras na lilitaw ang isang bagong network block - nakabuo kami ng koneksyon ng client-to-node at node-to-node na socket. Kapag nakatanggap ang isang node ng bagong transaksyon, sinusuri nito ang bisa nito at ipinapasa ito sa iba pang mga node. Available ang transaksyon sa mga kliyente ng messenger bago pa man mangyari ang pinagkasunduan at isama sa block. Sa ganitong paraan, agad kaming maghahatid ng mga mensahe, tulad ng mga regular na instant messenger.

Upang iimbak ang address book, gumawa kami ng KVS - Key-Value Storage - isa itong uri ng transaksyon kung saan asset hindi NaCl-box ang naka-encrypt, ngunit NaCl-secretbox. Ito ay kung paano iniimbak ng messenger ang iba pang data.

Ang mga paglilipat ng file/imahe at panggrupong chat ay nangangailangan pa rin ng maraming trabaho. Siyempre, sa blunder-and-blunder na format, maaari itong "ma-screw up" nang mabilis, ngunit gusto naming mapanatili ang parehong antas ng privacy.

Oo, mayroon pa ring kailangang gawin - sa isip, ang tunay na privacy ay ipinapalagay na ang mga user ay hindi kumonekta sa mga pampublikong network node, ngunit magtataas ng kanilang sarili. Ilang porsyento ng mga user sa tingin mo ang gumagawa nito? Tama iyon, 0. Nagawa naming bahagyang nalutas ang isyung ito sa bersyon ng Tor ng messenger.

Napatunayan namin na maaaring umiral ang isang messenger sa blockchain. Dati, mayroon lamang isang pagtatangka noong 2012 - bitmessage, na nabigo dahil sa mahabang oras ng paghahatid ng mensahe, pag-load ng CPU, at kakulangan ng mga mobile application.

At ang pag-aalinlangan ay dahil sa ang katunayan na ang mga messenger sa blockchain ay nauuna sa kanilang panahon - ang mga tao ay hindi pa handa na kumuha ng responsibilidad para sa kanilang account, ang pagmamay-ari ng personal na impormasyon ay hindi pa uso, at ang teknolohiya ay hindi nagpapahintulot ng mataas na bilis sa blockchain. Higit pang mga teknolohikal na analogue ng aming proyekto ang susunod na lilitaw. Makikita mo.

Pinagmulan: www.habr.com

Magdagdag ng komento