Cumu funziona un messaggeru decentralizatu nantu à a blockchain?

À u principiu di 2017, avemu cuminciatu à creà un messageru nantu à u blockchain [nome è ligame sò in u prufilu] discutendu i vantaghji nantu à i messageri P2P classici.

Andatu 2.5 annu, è pudemu cunfirmà u nostru cuncettu: l'applicazioni di messageria sò avà dispunibuli per iOS, Web PWA, Windows, GNU/Linux, Mac OS è Android.

Oghje vi diceremu cumu funziona u messenger blockchain è cumu l'applicazioni di u cliente ponu travaglià cù a so API.
Cumu funziona un messaggeru decentralizatu nantu à a blockchain?

Vulemu chì u blockchain risolve i prublemi di sicurità è privacy di i messageri P2P classici:

  • Un clic per creà un contu - senza telefoni o e-mail, nè accessu à libri d'indirizzu o geolocazioni.
  • L'interlocutori ùn stabiliscenu mai cunnessione diretta; tutta a cumunicazione si faci per un sistema distribuitu di nodi. L'indirizzi IP di l'utilizatori ùn sò micca accessibili per l'altri.
  • Tutti i missaghji sò criptati End-to-End curve25519xsalsa20poly1305. Sembra chì questu ùn sorprenderà à nimu, ma u nostru codice fonte hè apertu.
  • L'attaccu MITM hè esclusu - ogni missaghju hè una transazzione è hè firmatu da Ed25519 EdDSA.
  • U missaghju finisci in u so propiu bloccu. Cuerenza è timestamp Ùn pudete micca riparà i blocchi, è dunque l'ordine di i missaghji.
  • "Ùn aghju micca dettu chì" ùn hà micca travagliatu cù missaghji nantu à u blockchain.
  • Ùn ci hè micca una struttura cintrali chì faci cuntrolli nantu à l'"autenticità" di un missaghju. Questu hè fattu da un sistema distribuitu di nodi basatu annantu à u cunsensu, è hè propiu di l'utilizatori.
  • Impussibilità di censura - i cunti ùn ponu micca esse bluccati è i missaghji ùn ponu micca esse eliminati.
  • Blockchain 2FA hè una alternativa à l'infernale 2FA via SMS, arruvinatu assai salute.
  • A capacità di uttene tutte e vostre conversazioni da qualsiasi dispositivu in ogni mumentu significa chì ùn avete micca bisognu di guardà conversazioni in u locu.
  • Cunfirmazione di u messagiu. Micca à u dispusitivu di l'utilizatori, ma à a reta. Essenzialmente, questu hè a cunferma di a capacità di u destinatariu di leghje u vostru messagiu. Questa hè una funzione utile per mandà notificazioni critiche.

I benefici di Blockchain includenu ancu una integrazione stretta cù e cripthe di monete Ethereum, Dogecoin, Lisk, Dash, Bitcoin (questu hè sempre in prugressu) è a capacità di mandà tokens in chats. Avemu ancu fattu un scambiatore di criptu integratu.

E poi - cumu tuttu funziona.

Un missaghju hè una transazzione

Tutti sò digià abituati à u fattu chì e transazzioni in u blockchain trasferisce tokens (muniti) da un utilizatore à l'altru. Cum'è Bitcoin. Avemu creatu un tipu speziale di transazzione per trasmette missaghji.

Per mandà un missaghju in un messenger nantu à u blockchain, avete bisognu di passà per parechji passi:

  1. Cripte u testu di u messagiu
  2. Mettite u testu cifratu in una transazzione
  3. Firmà a transazzione
  4. Mandate una transazzione à qualsiasi node di a reta
  5. Un sistema distribuitu di nodi determina l'"autenticità" di un messagiu
  6. Se tuttu hè bè, a transazzione cù u messagiu hè inclusa in u prossimu bloccu
  7. U destinatariu recupera a transazzione di missaghju è decripta

I passi 1-3 è 7 sò realizati in u locu nantu à u cliente, è i passi 5-6 sò realizati nantu à l'ospiti.

Criptazione di i missaghji

U messagiu hè criptatu cù a chjave privata di u mittente è a chjave publica di u destinatariu. Pigliemu a chjave publica da a reta, ma per questu, u cuntu di u destinatariu deve esse inizializatu, vale à dì, avè almenu una transazzione. Pudete aduprà una dumanda REST GET /api/accounts/getPublicKey?address={ADAMANT address}, è quandu caricate chats, i chjavi publichi di l'interlocutori seranu digià dispunibili.

Cumu funziona un messaggeru decentralizatu nantu à a blockchain?

U messenger cripta i missaghji cù l'algoritmu curve25519xsalsa20poly1305 (Scatola NaCl). Siccomu u contu cuntene chjavi Ed25519, per furmà una scatula, i chjavi devenu esse prima cunvertiti in Curve25519 Diffie-Hellman.

Eccu un esempiu in 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)
  }
}

Formà una transazzione cù un missaghju

A transazzione hà a seguente struttura generale:

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

Per una transazzione di missaghju, u più impurtante hè asset - avete bisognu di mette un missaghju in l'ughjettu chat cù struttura:

  • message - salvà u messagiu criptatu
  • own_message - nulla
  • type - tipu di missaghju

I missaghji sò ancu divisi in tipi. Essenzialmente, u paràmetru type vi dice cumu capisce message. Pudete mandà solu un testu, o pudete mandà un ughjettu cù cose interessanti in l'internu - per esempiu, questu hè cumu u messenger face trasferimenti di criptocurrency in chats.

In u risultatu, creamu una transazzione:

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

Firma di transazzione

Per assicurà chì tutti sò cunfidenti in l'autenticità di u mittente è u destinatariu, u tempu di mandà è u cuntenutu di u missaghju, a transazzione hè firmata. Una firma digitale permette di verificà l'autenticità di una transazzione cù una chjave publica - una chjave privata ùn hè micca necessariu per questu.

Ma a firma stessa hè realizata cù a chjave privata:

Cumu funziona un messaggeru decentralizatu nantu à a blockchain?

U diagramma mostra chì avemu prima a transazzione cù SHA-256 è dopu firmà Ed25519 EdDSA è ottene una firma signature, è l'ID di transazzione hè parti di l'hash SHA-256.

Esempiu di implementazione:

1 - Formà un bloccu di dati, cumpresu un missaghju

/**
 * 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 - Cunta SHA-256 da u bloccu di dati

/**
 * 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 - Firmà a transazzione

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

Mandate una transazzione cù un messagiu à un node di rete

Siccomu a reta hè decentralizata, qualsiasi di i nodi cù una API aperta farà. Fà una dumanda POST à ​​l'endpoint api/transactions:

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

In risposta, riceveremu un ID di transazzione di u tipu

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

Validazione di a transazzione

Un sistema distribuitu di nodi, basatu annantu à u cunsensu, determina l'"autenticità" di u missaghju di transazzione. Da quale è à quale, quandu, se u messagiu hè statu rimpiazzatu cù un altru, è se l'ora di l'invio hè stata indicata currettamente. Questu hè un vantaghju assai impurtante di u blockchain - ùn ci hè micca una struttura cintrali chì hè rispunsevule per a verificazione, è a sequenza di i missaghji è u so cuntenutu ùn ponu esse falsificati.

Prima, un node verifica l'accuratezza, è poi u manda à l'altri - se a maiuranza dice chì tuttu hè in ordine, a transazzione serà inclusa in u prossimu blocu di a catena - questu hè cunsensu.

Cumu funziona un messaggeru decentralizatu nantu à a blockchain?

A parte di u codice di u nodu chì hè rispunsevule per i cuntrolli pò esse vistu in GitHub - validator.js и verificate.js. Iè, u node corre nantu à Node.js.

Includite una transazzione cù un messagiu in un bloccu

Se u cunsensu hè righjuntu, a transazzione cù u nostru missaghju serà inclusa in u prossimu bloccu cù altre transazzione validu.

I blocchi anu una sequenza stretta, è ogni bloccu sussegwenti hè furmatu basatu annantu à l'hash di blocchi precedenti.

Cumu funziona un messaggeru decentralizatu nantu à a blockchain?

U puntu hè chì u nostru missaghju hè ancu inclusu in questa sequenza è ùn pò micca esse "rearranged". Sè parechji missaghji falà in un bloccu, u so ordine sarà determinata da timestamp missaghji.

Lettura di missaghji

L'applicazione di messenger recupera transacciones da u blockchain chì sò mandati à u destinatariu. Per questu avemu fattu un puntu finale api/chatrooms.

Tutte e transazzione sò dispunibuli per tutti - pudete riceve missaghji criptati. Ma solu u destinatariu pò decifrare cù a so chjave privata è a chjave publica di u mittente:

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

È chì altru ?

Siccomu i missaghji sò mandati in questu modu in circa 5 seconde - questu hè u tempu chì appare un novu bloccu di rete - avemu ghjuntu cun una cunnessione di socket client-à-node è node-à-node. Quandu un node riceve una nova transazzione, verifica a so validità è u trasmette à altri nodi. A transazzione hè dispunibule per i clienti di messageria ancu prima chì u cunsensu si faci è l'inclusione in u bloccu. In questu modu, daremu i missaghji istantaneamente, cum'è i messageri istantanei regulari.

Per almacenà u libru di indirizzu, avemu fattu KVS - Key-Value Storage - questu hè un altru tipu di transazzione in quale asset ùn hè micca NaCl-box chì hè criptatu, ma NaCl-secretbox. Questu hè cumu u messenger guarda altre dati.

I trasferimenti di file / imaghjini è i chats di gruppu necessitanu sempre assai travagliu. Di sicuru, in u formatu blunder-and-blunder questu pò esse "screwed up" rapidamente, ma vulemu mantene u listessu livellu di privacy.

Iè, ci hè ancu un travagliu per esse fattu - idealmente, a vera privacy assume chì l'utilizatori ùn anu micca cunnette à i nodi di a rete publica, ma suscitarà u so propiu. Chì percentuale di l'utilizatori pensate chì faci questu? Hè propiu, 0. Pudemu risolve parzialmente stu prublema cù a versione Tor di u messenger.

Avemu pruvucatu chì un messageru nantu à a blockchain pò esse. Prima, ci era solu un tentativu in 2012 - bitmessage, chì hà fiascatu per via di lunghi tempi di consegna di messagi, carica di CPU, è mancanza di applicazioni mobili.

È u scetticismu hè duvuta à u fattu chì i messageri nantu à u blockchain sò davanti à u so tempu - a ghjente ùn hè micca pronta per piglià a rispunsabilità di u so contu, pussede l'infurmazioni persunali ùn hè ancu una tendenza, è a tecnulugia ùn permette micca alta velocità in u blockchain. Più analoghi tecnologichi di u nostru prughjettu appariscenu dopu. Viderete.

Source: www.habr.com

Add a comment