Орталықтандырылмаған мессенджер блокчейнде қалай жұмыс істейді?

2017 жылдың басында классикалық P2P мессенджерлерінен артықшылықтарды талқылау арқылы блокчейнде [аты мен сілтемесі профильде] мессенджер құруды бастадық.

Өтті 2.5 жылы, және біз өз тұжырымдамамызды растай алдық: messenger қолданбалары енді iOS, Web PWA, Windows, GNU/Linux, Mac OS және Android үшін қол жетімді.

Бүгін біз сізге blockchain мессенджері қалай жұмыс істейтінін және клиенттік қосымшалардың оның API-мен қалай жұмыс істейтінін айтып береміз.
Орталықтандырылмаған мессенджер блокчейнде қалай жұмыс істейді?

Біз блокчейннің классикалық P2P мессенджерлерінің қауіпсіздік және құпиялылық мәселелерін шешуін қаладық:

  • Тіркелгі жасау үшін бір рет нұқыңыз - телефондар немесе электрондық пошталар жоқ, мекенжай кітаптарына немесе геолокацияларға қол жетімділік жоқ.
  • Әңгімелесушілер ешқашан тікелей байланыс орнатпайды, барлық байланыс түйіндердің бөлінген жүйесі арқылы жүзеге асады. Пайдаланушылардың IP мекенжайлары бір-біріне қол жетімді емес.
  • Барлық хабарлар End-to-End curve25519xsalsa20poly1305 шифрланған. Бұл ешкімді таң қалдырмайтын сияқты, бірақ біздің бастапқы кодымыз ашық.
  • MITM шабуылы алынып тасталды - әрбір хабарлама транзакция болып табылады және Ed25519 EdDSA қол қояды.
  • Хабарлама өз блогында аяқталады. Жүйелілік және timestamp Сіз блоктарды, демек, хабарлардың ретін түзете алмайсыз.
  • «Мен бұлай айтқан жоқпын» блокчейндегі хабарламалармен жұмыс істемейді.
  • Хабарламаның «шынайылығын» тексеретін орталық құрылым жоқ. Мұны консенсусқа негізделген түйіндердің бөлінген жүйесі жасайды және ол пайдаланушыларға тиесілі.
  • Цензураның мүмкін еместігі - тіркелгілерді бұғаттауға және хабарламаларды жоюға болмайды.
  • Blockchain 2FA - бұл SMS арқылы тозақ 2FA-ға балама, көп денсаулықты бұзды.
  • Барлық сөйлесулерді кез келген құрылғыдан кез келген уақытта алу мүмкіндігі сөйлесулерді жергілікті жерде сақтаудың қажеті жоқ дегенді білдіреді.
  • Хабарламаның жеткізілуін растау. Пайдаланушының құрылғысына емес, желіге. Негізінде, бұл алушының сіздің хабарламаңызды оқу мүмкіндігін растау. Бұл маңызды хабарландыруларды жіберуге арналған пайдалы мүмкіндік.

Blockchain артықшылықтары 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, ал транзакция идентификаторы 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'

Жауап ретінде біз түрдегі транзакция идентификаторын аламыз

{
    "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 жылы бір ғана әрекет болды - биттік хабар, ол хабарды жеткізудің ұзақ уақытына, процессордың жүктелуіне және мобильді қолданбалардың болмауына байланысты сәтсіз аяқталды.

Ал скептицизм блокчейндегі мессенджерлердің өз уақытынан озып кетуіне байланысты - адамдар өз аккаунты үшін жауапкершілікті алуға дайын емес, жеке ақпаратқа ие болу әлі тренд емес, технология блокчейндегі жоғары жылдамдыққа мүмкіндік бермейді. Келесіде жобамыздың тағы да технологиялық аналогтары пайда болады. Сен көресің.

Ақпарат көзі: www.habr.com

пікір қалдыру