Ինչպե՞ս է ապակենտրոնացված մեսենջերն աշխատում բլոկչեյնի վրա:

2017 թվականի սկզբին մենք սկսեցինք ստեղծել մեսենջեր բլոկչեյնում [անունը և հղումը գտնվում են պրոֆիլում]՝ քննարկելով դասական P2P մեսենջերների նկատմամբ առավելությունները:

Անցել է 2.5 տարի, և մենք կարողացանք հաստատել մեր հայեցակարգը. մեսենջերային հավելվածներն այժմ հասանելի են iOS-ի, Web PWA-ի, Windows-ի, GNU/Linux-ի, Mac OS-ի և Android-ի համար:

Այսօր մենք ձեզ կպատմենք, թե ինչպես է աշխատում բլոկչեյն մեսենջերը և ինչպես հաճախորդի հավելվածները կարող են աշխատել իր API-ի հետ:
Ինչպե՞ս է ապակենտրոնացված մեսենջերն աշխատում բլոկչեյնի վրա:

Մենք ցանկանում էինք, որ բլոկչեյնը լուծեր դասական P2P մեսենջերների անվտանգության և գաղտնիության խնդիրները.

  • Մեկ կտտոցով հաշիվ ստեղծելու համար՝ հեռախոսներ կամ էլ.
  • Զրուցակիցները երբեք ուղիղ կապեր չեն հաստատում, ամբողջ շփումը տեղի է ունենում հանգույցների բաշխված համակարգի միջոցով։ Օգտատերերի IP հասցեները հասանելի չեն միմյանց համար:
  • Բոլոր հաղորդագրությունները կոդավորված են End-to-End curve25519xsalsa20poly1305: Թվում է, թե սա ոչ մեկին չի զարմացնի, բայց մեր սկզբնական կոդը բաց է։
  • MITM հարձակումը բացառված է. յուրաքանչյուր հաղորդագրություն գործարք է և ստորագրված է Ed25519 EdDSA-ի կողմից:
  • Հաղորդագրությունն ավարտվում է իր սեփական բլոկում: Հետևողականություն և timestamp Դուք չեք կարող շտկել բլոկները, հետևաբար՝ հաղորդագրությունների հերթականությունը:
  • «Ես դա չեմ ասել» չի աշխատի բլոկչեյնի հաղորդագրությունների հետ:
  • Չկա կենտրոնական կառույց, որը ստուգում է հաղորդագրության «ճշգրիտությունը»: Դա արվում է հանգույցների բաշխված համակարգով, որը հիմնված է կոնսենսուսի վրա, և այն պատկանում է օգտագործողներին:
  • Գրաքննության անհնարինություն. հաշիվները չեն կարող արգելափակվել և հաղորդագրությունները չեն կարող ջնջվել:
  • Blockchain 2FA-ն այլընտրանք է դժոխային 2FA-ին SMS-ի միջոցով, շատ առողջություն է փչացրել:
  • Ձեր բոլոր խոսակցությունները ցանկացած սարքից ցանկացած պահի ստանալու հնարավորությունը նշանակում է, որ դուք ընդհանրապես պետք չէ խոսակցությունները պահել տեղում:
  • Հաղորդագրության առաքման հաստատում: Ոչ թե օգտատիրոջ սարքին, այլ ցանցին։ Ըստ էության, սա ձեր հաղորդագրությունը կարդալու ստացողի ունակության հաստատումն է: Սա օգտակար հատկություն է կարևոր ծանուցումներ ուղարկելու համար:

Բլոկչեյնի առավելությունները ներառում են նաև սերտ ինտեգրում Ethereum, Dogecoin, Lisk, Dash, Bitcoin կրիպտոարժույթների հետ (այս մեկը դեռ ընթացքի մեջ է) և չաթերում նշաններ ուղարկելու հնարավորությունը: Մենք նույնիսկ ներկառուցված կրիպտոփոխանակիչ ենք պատրաստել:

Եվ հետո - ինչպես է ամեն ինչ աշխատում:

Հաղորդագրությունը գործարք է

Բոլորն արդեն սովոր են այն փաստին, որ բլոկչեյնով գործարքները փոխանցում են ժետոններ (մետաղադրամներ) մի օգտագործողից մյուսը: Bitcoin-ի նման: Մենք ստեղծել ենք հատուկ տեսակի գործարք՝ հաղորդագրությունների փոխանցման համար:

Բլոկչեյնի վրա մեսենջերում հաղորդագրություն ուղարկելու համար հարկավոր է անցնել մի քանի քայլ.

  1. Գաղտնագրեք հաղորդագրության տեքստը
  2. Ներդրեք ծածկագրված տեքստը գործարքի մեջ
  3. Ստորագրեք գործարքը
  4. Գործարք ուղարկեք ցանցի ցանկացած հանգույց
  5. Հանգույցների բաշխված համակարգը որոշում է հաղորդագրության «իսկականությունը»:
  6. Եթե ​​ամեն ինչ կարգին է, հաղորդագրության հետ գործարքը ներառված է հաջորդ բլոկում
  7. Ստացողը առբերում է հաղորդագրության գործարքը և վերծանում

1-3 և 7-րդ քայլերը կատարվում են տեղական հաճախորդի վրա, իսկ 5-6-րդ քայլերը՝ հյուրընկալողների վրա:

Հաղորդագրությունների կոդավորումը

Հաղորդագրությունը կոդավորված է ուղարկողի անձնական բանալիով և ստացողի հանրային բանալիով: Մենք հանրային բանալին կվերցնենք ցանցից, բայց դրա համար ստացողի հաշիվը պետք է նախաստորագրված լինի, այսինքն՝ ունենա առնվազն մեկ գործարք: Դուք կարող եք օգտագործել REST հարցումը GET /api/accounts/getPublicKey?address={ADAMANT address}, իսկ չաթերը բեռնելիս արդեն հասանելի կլինեն զրուցակիցների հանրային բանալիները։

Ինչպե՞ս է ապակենտրոնացված մեսենջերն աշխատում բլոկչեյնի վրա:

Մեսսենջերը կոդավորում է հաղորդագրությունները՝ օգտագործելով curve25519xsalsa20poly1305 ալգորիթմը (NaCl տուփ) Քանի որ հաշիվը պարունակում է Ed25519 ստեղներ, տուփ ձևավորելու համար բանալիները նախ պետք է փոխարկվեն Curve25519 Diffie-Hellman-ի:

Ահա մի օրինակ 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)
  }
}

Հաղորդագրությամբ գործարքի ձևավորում

Գործարքն ունի հետևյալ ընդհանուր կառուցվածքը.

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

Հաղորդագրության գործարքի համար ամենակարևորն այն է asset - պետք է հաղորդագրություն տեղադրել օբյեկտում chat կառուցվածքով:

  • message - պահպանել կոդավորված հաղորդագրությունը
  • own_message - ոչ մի անգամ
  • type - հաղորդագրության տեսակը

Հաղորդագրությունները նույնպես բաժանվում են տեսակների. Ըստ էության, պարամետրը type պատմում է, թե ինչպես հասկանալ message. Դուք կարող եք ուղարկել պարզապես տեքստ, կամ կարող եք ուղարկել առարկա, որի ներսում հետաքրքիր բաներ կան, օրինակ՝ այսպես մեսենջերը կրիպտոարժույթի փոխանցումներ է կատարում չաթերում:

Արդյունքում մենք ստեղծում ենք գործարք.

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

Գործարքի ստորագրություն

Ապահովելու համար, որ բոլորը վստահ են ուղարկողի և ստացողի իսկության, ուղարկման ժամանակի և հաղորդագրության բովանդակության մեջ, գործարքը կնքվում է: Թվային ստորագրությունը թույլ է տալիս ստուգել գործարքի իսկությունը՝ օգտագործելով հանրային բանալին. դրա համար անձնական բանալի անհրաժեշտ չէ:

Բայց ստորագրությունն ինքնին կատարվում է անձնական բանալիով.

Ինչպե՞ս է ապակենտրոնացված մեսենջերն աշխատում բլոկչեյնի վրա:

Դիագրամը ցույց է տալիս, որ մենք նախ հեշավորում ենք գործարքը SHA-256-ով, այնուհետև ստորագրում ենք այն Ed25519 EdDSA և ստորագրություն ստանալ signature, և գործարքի ID-ն SHA-256 հեշի մի մասն է:

Իրականացման օրինակ.

1 — Ձևավորել տվյալների բլոկ, ներառյալ հաղորդագրություն

/**
 * 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 - Հաշվեք SHA-256 տվյալների բլոկից

/**
 * 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 — Ստորագրեք գործարքը

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

Ցանցի հանգույցին հաղորդագրությամբ գործարք ուղարկելը

Քանի որ ցանցը ապակենտրոնացված է, բաց API ունեցող հանգույցներից որևէ մեկը կկատարի: POST հարցում կատարելով մինչև վերջնակետ api/transactions:

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

Ի պատասխան մենք կստանանք գործարքի տիպի ID

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

Գործարքի վավերացում

Հանգույցների բաշխված համակարգը, որը հիմնված է կոնսենսուսի վրա, որոշում է գործարքի հաղորդագրության «իսկականությունը»: Ումի՞ց և ում, երբ, արդյո՞ք հաղորդագրությունը փոխարինվել է մեկ այլով, և արդյոք ճիշտ է նշված ուղարկելու ժամանակը։ Սա բլոկչեյնի շատ կարևոր առավելություն է՝ չկա կենտրոնական կառույց, որը պատասխանատու է ստուգման համար, և հաղորդագրությունների հաջորդականությունը և դրանց բովանդակությունը չեն կարող կեղծվել։

Նախ, մի հանգույցը ստուգում է ճշգրտությունը, այնուհետև այն ուղարկում է մյուսներին. եթե մեծամասնությունն ասում է, որ ամեն ինչ կարգին է, գործարքը կներառվի շղթայի հաջորդ բլոկում, սա կոնսենսուս է:

Ինչպե՞ս է ապակենտրոնացված մեսենջերն աշխատում բլոկչեյնի վրա:

Հանգույցի կոդի այն մասը, որը պատասխանատու է ստուգումների համար, կարելի է դիտել GitHub-ում. validator.js и verify.js. Այո, հանգույցն աշխատում է Node.js-ում:

Ներառյալ բլոկում հաղորդագրությամբ գործարք

Եթե ​​կոնսենսուս ձեռք բերվի, մեր հաղորդագրությամբ գործարքը կներառվի հաջորդ բլոկում այլ վավեր գործարքների հետ միասին:

Բլոկներն ունեն խիստ հաջորդականություն, և յուրաքանչյուր հաջորդ բլոկ ձևավորվում է նախորդ բլոկների հեշերի հիման վրա:

Ինչպե՞ս է ապակենտրոնացված մեսենջերն աշխատում բլոկչեյնի վրա:

Բանն այն է, որ մեր ուղերձը նույնպես ներառված է այս հաջորդականության մեջ և չի կարող «վերադասավորվել»: Եթե ​​մի քանի հաղորդագրություններ ընկնում են բլոկի մեջ, դրանց հերթականությունը կորոշվի ըստ timestamp հաղորդագրություններ:

Հաղորդագրությունների ընթերցում

Մեսսենջեր հավելվածը առբերում է բլոկչեյնից գործարքները, որոնք ուղարկվում են ստացողին: Դրա համար մենք վերջնակետ դրեցինք api/chatrooms.

Բոլոր գործարքները հասանելի են բոլորին. դուք կարող եք ստանալ կոդավորված հաղորդագրություններ: Բայց միայն ստացողը կարող է վերծանել՝ օգտագործելով իր անձնական և ուղարկողի հանրային բանալին.

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

Իսկ ուրիշ ի՞նչ։

Քանի որ հաղորդագրություններն այս ձևով առաքվում են մոտ 5 վայրկյանում, սա այն ժամանակն է, երբ հայտնվում է ցանցի նոր բլոկը, մենք ստեղծեցինք հաճախորդ-հանգույց և հանգույց-հանգույց վարդակից: Երբ հանգույցը ստանում է նոր գործարք, այն ստուգում է դրա վավերականությունը և այն փոխանցում այլ հանգույցներին: Գործարքը հասանելի է մեսենջերի հաճախորդներին նույնիսկ մինչև կոնսենսուսի առաջացումը և բլոկում ներառելը: Այս կերպ մենք անմիջապես կառաքենք հաղորդագրությունները, ինչպես սովորական ակնթարթային մեսենջերները:

Հասցեների գիրքը պահելու համար մենք պատրաստեցինք KVS - Key-Value Storage - սա գործարքի ևս մեկ տեսակ է, որում asset դա NaCl-արկղը չէ, որը կոդավորված է, այլ NaCl-գաղտնի տուփ. Ահա թե ինչպես է մեսենջերը պահպանում այլ տվյալներ։

Ֆայլերի/պատկերների փոխանցումները և խմբային զրույցները դեռևս մեծ աշխատանք են պահանջում: Իհարկե, սխալ և կոպիտ ձևաչափում սա կարող է արագ «փչանալ», բայց մենք ցանկանում ենք պահպանել գաղտնիության նույն մակարդակը:

Այո, դեռ անելիքներ կան. իդեալական, իրական գաղտնիությունը ենթադրում է, որ օգտվողները չեն միանա հանրային ցանցի հանգույցներին, այլ կբարձրացնեն իրենց սեփականը: Ձեր կարծիքով օգտատերերի քանի՞ տոկոսն է դա անում: Ճիշտ է, 0: Մենք կարողացանք մասնակիորեն լուծել այս խնդիրը մեսենջերի Tor տարբերակով:

Մենք ապացուցել ենք, որ բլոկչեյնի վրա մեսենջեր կարող է գոյություն ունենալ: Նախկինում ընդամենը մեկ փորձ է եղել՝ 2012թ. bitmessage, որը ձախողվեց հաղորդագրությունների առաքման երկար ժամանակի, պրոցեսորի ծանրաբեռնվածության և բջջային հավելվածների բացակայության պատճառով:

Իսկ թերահավատությունը պայմանավորված է նրանով, որ բլոկչեյնի մեսենջերներն իրենց ժամանակից առաջ են. մարդիկ պատրաստ չեն պատասխանատվություն ստանձնել իրենց հաշվի համար, անձնական տեղեկատվության տիրապետումը դեռ միտում չէ, և տեխնոլոգիան թույլ չի տալիս բլոկչեյնի բարձր արագություն: Մեր նախագծի ավելի շատ տեխնոլոգիական անալոգներ կհայտնվեն հաջորդիվ: Դուք կտեսնեք.

Source: www.habr.com

Добавить комментарий