Si funksionon një mesazh i decentralizuar në blockchain

Në fillim të vitit 2017, ne filluam të krijojmë një mesazhues në blockchain [emri dhe lidhja janë në profil] duke diskutuar për Avantazhet përpara mesazhuesve klasikë P2P.

Kaluan 2.5 vjet, dhe arritëm të konfirmojmë konceptin tonë: tani janë të disponueshme aplikacionet e mesazhuesit për iOS, Web PWA, Windows, GNU/Linux, Mac OS dhe Android.

Sot do të flasim për strukturën e mesazhuesit në blockchain dhe si aplikacionet klienti punojnë me API-në e tij.
Si funksionon një mesazh i decentralizuar në blockchain

Donim që blockchain të zgjidhte problemet e sigurisë dhe privatësisë së mesazhuesve klasikë P2P:

  • NjĂ« klik pĂ«r tĂ« krijuar njĂ« llogari — asnjĂ« numĂ«r telefoni dhe email, nuk ka qasje nĂ« adresat e kontakteve dhe gjeolokacionet.
  • BashkĂ«biseduesit kurrĂ« nuk krijojnĂ« lidhje direkte, e gjithĂ« komunikimi kalon pĂ«rmes njĂ« sistemi tĂ« shpĂ«rndarĂ« nodesh. Adresat IP tĂ« pĂ«rdoruesve nuk janĂ« tĂ« aksesueshme nga njĂ«ri-tjetri.
  • TĂ« gjitha mesazhet janĂ« tĂ« koduara End-to-End curve25519xsalsa20poly1305. NĂ« pamje tĂ« parĂ« kjo nuk Ă«shtĂ« e habitshme, por ne kemi kodin burimor tĂ« hapur.
  • Sulmi MITM Ă«shtĂ« i pĂ«rjashtuar — çdo mesazh Ă«shtĂ« njĂ« transaksion dhe nĂ«nshkruhet me Ed25519 EdDSA.
  • Mesazhi shkon nĂ« bllokun e tij. Rregulli dhe timestamp blloqet nuk mund tĂ« ndryshohen, dhe, pĂ«r pasojĂ«, as rendi i mesazheve.
  • “Nuk e thashĂ« kĂ«tĂ«â€ nuk do tĂ« funksionojĂ« me mesazhet nĂ« blockchain.
  • Nuk ka njĂ« strukturĂ« qendrore qĂ« bĂ«n kontrollin e “besueshmĂ«risĂ«â€ sĂ« mesazheve. Kjo bĂ«het nga sistemi i shpĂ«rndarĂ« i nodesh nĂ« bazĂ« tĂ« konsensusit, dhe ai i pĂ«rket pĂ«rdoruesve.
  • PamundĂ«sia e censurĂ«s — llogaritĂ« nuk mund tĂ« bllokohen dhe mesazhet nuk mund tĂ« fshihen.
  • Blockchain 2FA — njĂ« alternativĂ« ndaj 2FA fatkeq nĂ« SMS, e cila ka prishur shumĂ« shĂ«ndet.
  • MundĂ«sia pĂ«r tĂ« marrĂ« tĂ« gjitha bisedat tuaja nga çdo pajisje nĂ« çdo kohĂ« — kjo Ă«shtĂ« mundĂ«sia pĂ«r tĂ« mos ruajtur bisedat nĂ« mĂ«nyrĂ« lokale fare.
  • Konfirmimi i dorĂ«zimit tĂ« mesazheve. Jo nĂ« pajisjen e pĂ«rdoruesit, por nĂ« rrjet. NĂ« thelb, kjo Ă«shtĂ« konfirmimi i mundĂ«sisĂ« sĂ« marrĂ«sit pĂ«r tĂ« lexuar mesazhin tuaj. Kjo Ă«shtĂ« njĂ« veçori e dobishme pĂ«r dĂ«rgimin e njoftimeve kritike.

Si avantazhe të blockchain-it janë gjithashtu integrimi i ngushtë me kriptovalutat Ethereum, Dogecoin, Lisk, Dash, Bitcoin (ky ende është në proces) dhe mundësia për të dërguar tokene në biseda. Ne madje kemi krijuar një shpërndarës kripto të integruar.

Dhe pastaj — si funksionon e gjithĂ« kjo.

Mesazhi është një transaksion.

Të gjithë janë mësuar tashmë se transaksionet në blockchain transferojnë tokene (monedha) nga një përdorues te tjetri. Si tek bitcoin. Ne kemi krijuar një lloj të veçantë transaksionesh për dërgimin e mesazheve.

Për të dërguar një mesazh në mesazherin në blockchain, duhet të kaloni disa etapa:

  1. Kriptoni tekstin e mesazhit
  2. Vendosni tekstin e kriptuar në transaksion
  3. Nënshkruani transaksionin
  4. Dërgoni transaksionin në çdo nyje të rrjetit
  5. Sistemi i shpĂ«rndarĂ« i nyjeve pĂ«rcakton “besueshmĂ«rinĂ«â€ e mesazhit
  6. NĂ«se gjithçka Ă«shtĂ« OK — transaksioni me mesazhin pĂ«rfshihet nĂ« bllokun e ardhshĂ«m
  7. Marrësi nxjerr transaksionin me mesazhin dhe e dekripton

Etapat 1–3 dhe 7 kryhen lokalish nĂ« klient, ndĂ«rsa 5–6 nĂ« nyjet e rrjetit.

Kriptimi i mesazhit

Mesazhi kriptohet me çelĂ«sin privat tĂ« dĂ«rguesit dhe çelĂ«sin publik tĂ« marrĂ«sit. ÇelĂ«si publik do ta marrim nga rrjeti, por pĂ«r kĂ«tĂ« llogaria e marrĂ«sit duhet tĂ« jetĂ« e iniciuar, domethĂ«nĂ«, tĂ« ketĂ« tĂ« paktĂ«n njĂ« transaksion. Mund tĂ« pĂ«rdoret njĂ« kĂ«rkesĂ« REST GET /api/accounts/getPublicKey?address={ADAMANT address}, dhe gjatĂ« ngarkimit tĂ« bisedave çelĂ«sat publikĂ« tĂ« bashkĂ«biseduesve do tĂ« jenĂ« tashmĂ« tĂ« pranishĂ«m.

Si funksionon një mesazh i decentralizuar në blockchain

Mesazheri kripton mesazhet me algoritmin curve25519xsalsa20poly1305 (NaCl Box). Duke pasur parasysh se llogaria përmban çelësa Ed25519, për formimin e box-it më parë çelësat duhet të konvertohen në Curve25519 Diffie-Hellman.

Këtu është një shembull në 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)
  }
}

Formimi i transaksionit me mesazh

Transaksioni ka një strukturë të tillë të përgjithshme:

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

PĂ«r transaksionin-mesazh, vlera mĂ« e rĂ«ndĂ«sishme Ă«shtĂ« asset — nĂ« tĂ« duhet tĂ« vendoset mesazhi nĂ« njĂ« objekt bisedĂ« me strukturĂ«n:

  • message — ruajmĂ« mesazhin e kriptuar
  • own_message — nonce
  • lloji — tipi i mesazhit

Mesazhet gjithashtu ndahen nĂ« tipe. NĂ« thelb, parametri lloji tregon se si tĂ« kuptohet message. Mund tĂ« dĂ«rgoni thjesht tekst, ose mund tĂ« dĂ«rgoni njĂ« objekt me interesat brenda — pĂ«r shembull, kĂ«shtu mesazheri bĂ«n transferimet e kriptomonedhave nĂ« biseda.

Në fund formojmë transaksionin:

{
  "transaction": {
    "type": 8,
    "amount": 0,
    "senderId": "U12499126640447739963",
    "senderPublicKey": "e9cafb1e7b403c4cf247c94f73ee4cada367fcc130cb3888219a0ba0633230b6",
    "asset": {
      "chat": {
        "message": "cb682accceef92d7cddaaddb787d1184ab5428",
        "own_message": "e7d8f90ddf7d70efe359c3e4ecfb5ed3802297b248eacbd6",
        "type": 1
      }
    },
    "recipientId": "U15677078342684640219",
    "timestamp": 63228087,
    "signature": "këtu do të jetë nënshkrimi"
  }
}

Nënshkrimi i transaksionit

PĂ«r tĂ« siguruar besueshmĂ«rinĂ« e dĂ«rguesit dhe marrĂ«sit, si dhe kohĂ«n e dĂ«rgimit dhe pĂ«rmbajtjen e mesazhit, transaksioni nĂ«nshkruhet. NĂ«nshkrimi digjital lejon verifikimin e vĂ«rtetĂ«sisĂ« sĂ« transaksionit pĂ«rmes çelĂ«sit publik — çelĂ«si privat nuk Ă«shtĂ« i nevojshĂ«m.

Dhe nënshkrimi vetë realizohet me çelësin privat:

Si funksionon një mesazh i decentralizuar në blockchain

Nga skema duket se fillimisht e hedhim transaksionin nĂ« SHA-256 dhe mĂ« pas e nĂ«nshkruajmĂ« Ed25519 EdDSA dhe marrim nĂ«nshkrimin nĂ«nshkrim, ndĂ«rsa identifikuesi i transaksionit — Ă«shtĂ« njĂ« pjesĂ« e hashit SHA-256.

Shembuj i implementimit:

1 — FormojmĂ« bllokun e tĂ« dhĂ«nave, duke pĂ«rfshirĂ« mesazhin

/**
 * 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 — Llogarisim SHA-256 nga blloku i tĂ« dhĂ«nave

/**
 * 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 — NĂ«nshkruajmĂ« transaksionin

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

/**
 * Krijon një nënshkrim bazuar në një hash dhe një çelës çift.
 * @implementon {sodium}
 * @param {hash} hash
 * @param {keypair} keypair
 * @return {nënshkrim} nënshkrim
 *\/ 
adamant.sign = function (hash, keypair) {
  return sodium.crypto_sign_detached(hash, Buffer.from(keypair.privateKey, 'hex'))
}

Dërgimi i transaksionit me mesazh në nodën e rrjetit

Për shkak se rrjeti është i decentralizuar, mund të përdorim çfarëdo nga nodet me API të hapur. Bëjmë kërkesë POST në endpointin api/transactions:

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

Si përgjigje do të marrim ID e transaksionit të tipit

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

Verifikimi i besueshmërisë së transaksionit

Sistemi i shpĂ«rndarĂ« i nodave mbi bazĂ«n e konsensusit pĂ«rcakton "besueshmĂ«rinĂ«" e transaksionit-mesazhit. Nga kush dhe pĂ«r kĂ«, kur, a Ă«shtĂ« zĂ«vendĂ«suar mesazhi me njĂ« tjetĂ«r, dhe a Ă«shtĂ« koha e dĂ«rgimit e saktĂ«. Kjo Ă«shtĂ« njĂ« pĂ«rfitim shumĂ« i rĂ«ndĂ«sishĂ«m i blockchain — nuk ka njĂ« strukturĂ« qendrore, e cila pĂ«rgjegjĂ«se pĂ«r verifikimet, dhe rendi i mesazheve dhe pĂ«rmbajtja e tyre nuk mund tĂ« falsifikohen.

Fillimisht, besueshmĂ«rinĂ« kontrollon njĂ« nod, dhe mĂ« pas e shpĂ«rndan tek tĂ« tjerĂ«t — nĂ«se shumica thonĂ« se gjithçka Ă«shtĂ« nĂ« rregull, transaksioni do tĂ« pĂ«rfshihet nĂ« bllokun e ardhshĂ«m tĂ« zinxhirit — kjo Ă«shtĂ« konsensusi.

Si funksionon një mesazh i decentralizuar në blockchain

NjĂ« pjesĂ« e kodit tĂ« nodit, qĂ« pĂ«rgjigjet pĂ«r verifikimet, mund tĂ« shihet nĂ« GitHub — validator.js dhe verify.js. Ah, n roja punon nĂ« Node.js.

Përfshijmë transaksionin me mesazh në bllok

Nëse arrihet konsensusi, transaksioni me mesazhin tonë do të kalojë në blokun e ardhshëm së bashku me transaksione të tjera të vlefshme.

Blloqet kanë një renditje të rreptë, dhe çdo bllok tjetër formohet mbi baza të hash-eve të blloqeve të mëparshme.

Si funksionon një mesazh i decentralizuar në blockchain

Thelbi është se mesazhi ynë është gjithashtu i përfshirë në këtë renditje dhe nuk mund të "rregullohet". Nëse në bllok kalojnë disa mesazhe, rendi i tyre do të përcaktohet nga timestamp mesazhet.

Leximi i mesazheve

Aplikacioni-mesazher nxjerr transaksionet nga blockchain-i, të cilat i janë dërguar marrësit. Për këtë kemi krijuar pikën e përshkruar api/chatrooms.

TĂ« gjitha transaksionet janĂ« nĂ« dispozicion pĂ«r çdo njeri — mund tĂ« merren mesazhe tĂ« koduara. Por vetĂ«m marrĂ«si mund ta shqipĂ«rojĂ« atĂ« me çelĂ«sin e tij privat dhe çelĂ«sin publik tĂ« dĂ«rguesit:

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

ÇfarĂ« tjetĂ«r?

Duke pasur parasysh se mesazhet dĂ«rgohen nĂ« kĂ«tĂ« mĂ«nyrĂ« pĂ«r rreth 5 sekonda — koha e shfaqjes sĂ« bllokut tĂ« ri tĂ« rrjetit — ne kemi menduar pĂ«r njĂ« lidhje soket klient-nod dhe nod-nod. Kur nodi merr njĂ« transaksion tĂ« ri, ai kontrollon vlefshmĂ«rinĂ« e tij dhe e kalon te nodet e tjera. Transaksioni Ă«shtĂ« nĂ« dispozicion pĂ«r klientĂ«t-mesazherĂ« edhe para arritjes sĂ« konsensit dhe pĂ«rfshirjes nĂ« bllok. KĂ«shtu do t'i dĂ«rgojmĂ« mesazhet menjĂ«herĂ«, si mesazherĂ«t e zakonshĂ«m.

PĂ«r tĂ« ruajtur librin e adresave, ne krijuam KVS — Ruajtje ÇelĂ«s-VlerĂ« — ky Ă«shtĂ« njĂ« tjetĂ«r tip transaksionesh, nĂ« tĂ« cilat asset nuk kodifikohet NaCl-box, por NaCl-secretbox. KĂ«shtu mesazheri ruan tĂ« dhĂ«na tĂ« tjera.

Transferimi i skedarëve/imazheve dhe bisedat grupore kërkojnë ende shumë punë. Sigurisht, në formatin e shpejtë, mund të "shtohet" shpejt, por ne duam të ruajmë të njëjtin nivel privatësie.

Po, ka ende pĂ«r tĂ« punuar — nĂ« ideale, privatĂ«sia reale nĂ«nkupton qĂ« pĂ«rdoruesit tĂ« mos lidhen me nodet publike tĂ« rrjetit, por tĂ« vendosin tĂ« tyre. A mendoni ju se sa pĂ«rqind e pĂ«rdoruesve e bĂ«jnĂ« kĂ«tĂ«? E saktĂ«, 0. PjesĂ«risht kĂ«tĂ« çështje arritĂ«m ta zgjidhim me versionin Tor tĂ« mesazherit.

Ne provuam qĂ« mesazheri nĂ« blockchain mund tĂ« ekzistojĂ«. MĂ« parĂ« kishte vetĂ«m njĂ« pĂ«rpjekje nĂ« vitin 2012 — bitmessage, e pasuksesshme pĂ«r shkak tĂ« kohĂ«s sĂ« madhe tĂ« dĂ«rgimit tĂ« mesazheve, ngarkesĂ«s nĂ« procesor dhe mungesĂ«s sĂ« aplikacioneve mobile.

Skepticizmi lidhet me faktin se mesazherĂ«t nĂ« blockchain po e pĂ«rparojnĂ« kohĂ«n — njerĂ«zit nuk janĂ« gati tĂ« marrin pĂ«rgjegjĂ«sinĂ« pĂ«r llogarinĂ« e tyre, pronĂ«sia e informacionit personal nuk Ă«shtĂ« akoma nĂ« modĂ«, dhe teknologjitĂ« nuk mund tĂ« ofrojnĂ« shpejtĂ«si tĂ« larta nĂ« blockchain. Pas kĂ«saj do tĂ« shfaqen analogĂ« mĂ« teknologjikĂ« tĂ« projektit tonĂ«. Do ta shihni.

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster