Bagaimana cara kerja utusan terdesentralisasi di blockchain?

Pada awal tahun 2017, kami mulai membuat messenger di blockchain [nama dan tautan ada di profil] dengan mendiskusikan keunggulan dibandingkan messenger P2P klasik.

Hilang 2.5 tahun, dan kami dapat mengonfirmasi konsep kami: aplikasi messenger kini tersedia untuk iOS, Web PWA, Windows, GNU/Linux, Mac OS, dan Android.

Hari ini kami akan memberi tahu Anda cara kerja blockchain messenger dan bagaimana aplikasi klien dapat bekerja dengan API-nya.
Bagaimana cara kerja utusan terdesentralisasi di blockchain?

Kami ingin blockchain memecahkan masalah keamanan dan privasi pengirim pesan P2P klasik:

  • Satu klik untuk membuat akun - tidak ada telepon atau email, tidak ada akses ke buku alamat atau geolokasi.
  • Lawan bicara tidak pernah membuat koneksi langsung; semua komunikasi terjadi melalui sistem node yang terdistribusi. Alamat IP pengguna tidak dapat diakses satu sama lain.
  • Semua pesan dienkripsi kurva End-to-End25519xsalsa20poly1305. Tampaknya ini tidak akan mengejutkan siapa pun, tetapi kode sumber kami terbuka.
  • Serangan MITM dikecualikan - setiap pesan adalah transaksi dan ditandatangani oleh Ed25519 EdDSA.
  • Pesan tersebut berakhir di bloknya sendiri. Konsistensi dan timestamp Anda tidak dapat memperbaiki bloknya, dan karena itu urutan pesannya.
  • “Saya tidak mengatakan itu” tidak akan berfungsi dengan pesan di blockchain.
  • Tidak ada struktur pusat yang memeriksa “keaslian” suatu pesan. Hal ini dilakukan oleh sistem node terdistribusi berdasarkan konsensus, dan dimiliki oleh pengguna.
  • Ketidakmungkinan sensor - akun tidak dapat diblokir dan pesan tidak dapat dihapus.
  • Blockchain 2FA adalah alternatif dari 2FA yang mengerikan melalui SMS, merusak banyak kesehatan.
  • Kemampuan untuk mendapatkan semua percakapan Anda dari perangkat apa pun dan kapan pun berarti Anda tidak perlu menyimpan percakapan secara lokal sama sekali.
  • Konfirmasi pengiriman pesan. Bukan ke perangkat pengguna, tapi ke jaringan. Intinya, ini adalah konfirmasi kemampuan penerima untuk membaca pesan Anda. Ini adalah fitur yang berguna untuk mengirimkan pemberitahuan penting.

Manfaat Blockchain juga mencakup integrasi erat dengan cryptocurrency Ethereum, Dogecoin, Lisk, Dash, Bitcoin (yang ini masih dalam proses) dan kemampuan untuk mengirim token dalam obrolan. Kami bahkan membuat penukar kripto bawaan.

Dan kemudian - cara kerjanya.

Pesan adalah transaksi

Semua orang sudah terbiasa dengan kenyataan bahwa transaksi di blockchain mentransfer token (koin) dari satu pengguna ke pengguna lainnya. Seperti Bitcoin. Kami menciptakan jenis transaksi khusus untuk mengirimkan pesan.

Untuk mengirim pesan melalui messenger di blockchain, Anda perlu melalui beberapa langkah:

  1. Enkripsi teks pesan
  2. Masukkan ciphertext ke dalam transaksi
  3. Tanda tangani transaksinya
  4. Kirim transaksi ke node jaringan mana pun
  5. Sistem node yang terdistribusi menentukan “keaslian” suatu pesan
  6. Jika semuanya baik-baik saja, transaksi dengan pesan tersebut disertakan di blok berikutnya
  7. Penerima mengambil transaksi pesan dan mendekripsi

Langkah 1–3 dan 7 dilakukan secara lokal pada klien, dan langkah 5–6 dilakukan pada host.

Enkripsi pesan

Pesan dienkripsi dengan kunci pribadi pengirim dan kunci publik penerima. Kami akan mengambil kunci publik dari jaringan, tetapi untuk ini, akun penerima harus diinisialisasi, yaitu memiliki setidaknya satu transaksi. Anda dapat menggunakan permintaan REST GET /api/accounts/getPublicKey?address={ADAMANT address}, dan saat memuat obrolan, kunci publik lawan bicara sudah tersedia.

Bagaimana cara kerja utusan terdesentralisasi di blockchain?

Messenger mengenkripsi pesan menggunakan algoritma curve25519xsalsa20poly1305 (Kotak NaCl). Karena akun berisi kunci Ed25519, untuk membentuk kotak, kunci tersebut harus dikonversi terlebih dahulu ke Curve25519 Diffie-Hellman.

Berikut ini contoh dalam 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)
  }
}

Membentuk transaksi dengan pesan

Transaksi tersebut memiliki struktur umum sebagai berikut:

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

Untuk transaksi pesan, yang terpenting adalah asset - Anda perlu menempatkan pesan di objek tersebut chat dengan struktur:

  • message - simpan pesan terenkripsi
  • own_message -tidak pernah
  • type — jenis pesan

Pesan juga dibagi menjadi beberapa jenis. Intinya, parameternya type memberitahu Anda bagaimana memahaminya message. Anda dapat mengirim teks saja, atau Anda dapat mengirim objek dengan hal-hal menarik di dalamnya - misalnya, beginilah cara pengirim pesan melakukan transfer mata uang kripto dalam obrolan.

Hasilnya, kami membuat transaksi:

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

Tanda tangan transaksi

Untuk memastikan bahwa setiap orang yakin akan keaslian pengirim dan penerima, waktu pengiriman dan isi pesan, transaksi ditandatangani. Tanda tangan digital memungkinkan Anda memverifikasi keaslian transaksi menggunakan kunci publik - kunci pribadi tidak diperlukan untuk ini.

Namun penandatanganannya sendiri dilakukan menggunakan kunci privat:

Bagaimana cara kerja utusan terdesentralisasi di blockchain?

Diagram menunjukkan bahwa pertama-tama kita melakukan hashing pada transaksi dengan SHA-256 dan kemudian menandatanganinya Ed25519 EdDSA dan mendapatkan tanda tangan signature, dan ID transaksi adalah bagian dari hash SHA-256.

Contoh implementasi:

1 — Membentuk blok data, termasuk pesan

/**
 * 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 - Hitung SHA-256 dari blok data

/**
 * 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 — Menandatangani transaksi

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

Mengirim transaksi dengan pesan ke node jaringan

Karena jaringannya terdesentralisasi, node mana pun dengan API terbuka dapat digunakan. Membuat permintaan POST ke titik akhir api/transactions:

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

Sebagai tanggapan, kami akan menerima ID transaksi dari jenis tersebut

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

Validasi Transaksi

Sistem node yang terdistribusi, berdasarkan konsensus, menentukan “keaslian” pesan transaksi. Dari siapa dan kepada siapa, kapan, apakah pesan tersebut diganti dengan yang lain, dan apakah waktu pengiriman sudah ditentukan dengan benar. Ini adalah keuntungan yang sangat penting dari blockchain - tidak ada struktur pusat yang bertanggung jawab untuk verifikasi, dan urutan pesan serta isinya tidak dapat dipalsukan.

Pertama, satu node memeriksa keakuratannya, dan kemudian mengirimkannya ke node lain - jika mayoritas mengatakan semuanya beres, transaksi akan dimasukkan ke dalam blok rantai berikutnya - ini adalah konsensus.

Bagaimana cara kerja utusan terdesentralisasi di blockchain?

Bagian dari kode node yang bertanggung jawab untuk pemeriksaan dapat dilihat di GitHub - validator.js и verifikasi.js. Yap, node tersebut berjalan di Node.js.

Termasuk transaksi dengan pesan dalam satu blok

Jika tercapai musyawarah, maka transaksi dengan pesan kami akan dimasukkan pada blok berikutnya bersama dengan transaksi sah lainnya.

Blok memiliki urutan yang ketat, dan setiap blok berikutnya dibentuk berdasarkan hash dari blok sebelumnya.

Bagaimana cara kerja utusan terdesentralisasi di blockchain?

Intinya pesan kita juga termasuk dalam urutan ini dan tidak bisa “diatur ulang”. Jika beberapa pesan masuk ke dalam satu blok, urutannya akan ditentukan oleh timestamp pesan.

Membaca pesan

Aplikasi messenger mengambil transaksi dari blockchain yang dikirimkan ke penerima. Untuk ini kami membuat titik akhir api/chatrooms.

Semua transaksi tersedia untuk semua orang - Anda dapat menerima pesan terenkripsi. Namun hanya penerima yang dapat mendekripsi menggunakan kunci pribadinya dan kunci publik pengirim:

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

Apa lagi?

Karena pesan dikirimkan dengan cara ini dalam waktu sekitar 5 detik - ini adalah saat blok jaringan baru muncul - kami membuat koneksi soket klien-ke-node dan node-ke-node. Ketika sebuah node menerima transaksi baru, ia memeriksa validitasnya dan meneruskannya ke node lain. Transaksi tersedia untuk klien messenger bahkan sebelum konsensus terjadi dan dimasukkan dalam blok. Dengan cara ini kami akan mengirimkan pesan secara instan, sama seperti pesan instan biasa.

Untuk menyimpan buku alamat, kami membuat KVS - Penyimpanan Nilai Kunci - ini adalah jenis transaksi lain yang digunakan asset bukan kotak NaCl yang dienkripsi, tapi Kotak rahasia NaCl. Beginilah cara messenger menyimpan data lainnya.

Transfer file/gambar dan obrolan grup masih memerlukan banyak pekerjaan. Tentu saja, dalam format blunder-blunder hal ini dapat “dikacaukan” dengan cepat, namun kami ingin menjaga tingkat privasi yang sama.

Ya, masih ada pekerjaan yang harus diselesaikan - idealnya, privasi nyata mengasumsikan bahwa pengguna tidak akan terhubung ke node jaringan publik, tetapi akan meningkatkan node mereka sendiri. Menurut Anda, berapa persentase pengguna yang melakukan hal ini? Itu benar, 0. Kami dapat menyelesaikan sebagian masalah ini dengan messenger versi Tor.

Kami telah membuktikan bahwa utusan di blockchain bisa ada. Sebelumnya, hanya ada satu upaya pada tahun 2012 - pesan bit, yang gagal karena waktu pengiriman pesan yang lama, beban CPU, dan kurangnya aplikasi seluler.

Dan skeptisisme disebabkan oleh fakta bahwa pengirim pesan di blockchain lebih maju dari zamannya - orang belum siap untuk bertanggung jawab atas akun mereka, kepemilikan informasi pribadi belum menjadi tren, dan teknologi tidak memungkinkan kecepatan tinggi di blockchain. Analog teknologi lainnya dari proyek kami akan muncul berikutnya. Anda akan melihat.

Sumber: www.habr.com

Tambah komentar