كيف يعمل برنامج المراسلة اللامركزي على blockchain؟

في بداية عام 2017، بدأنا في إنشاء برنامج مراسلة على blockchain [الاسم والرابط موجودان في الملف الشخصي] من خلال مناقشة المزايا التي يتميز بها برنامج مراسلة P2P الكلاسيكي.

ذهب 2.5 العام الماضي، وتمكنا من تأكيد مفهومنا: تطبيقات المراسلة متاحة الآن لأنظمة iOS، وWeb PWA، وWindows، وGNU/Linux، وMac OS، وAndroid.

سنخبرك اليوم كيف يعمل برنامج blockchain messenger وكيف يمكن لتطبيقات العميل أن تعمل مع واجهة برمجة التطبيقات الخاصة به.
كيف يعمل برنامج المراسلة اللامركزي على blockchain؟

أردنا أن تعمل تقنية blockchain على حل مشكلات الأمان والخصوصية الخاصة بمراسلات P2P الكلاسيكية:

  • نقرة واحدة لإنشاء حساب - لا هواتف أو رسائل بريد إلكتروني، ولا إمكانية الوصول إلى دفاتر العناوين أو المواقع الجغرافية.
  • لا يقوم المحاورون أبدًا بإنشاء اتصالات مباشرة، بل تتم جميع الاتصالات من خلال نظام موزع من العقد. لا يمكن الوصول إلى عناوين IP الخاصة بالمستخدمين لبعضهم البعض.
  • يتم تشفير جميع الرسائل من خلال منحنى End-to-End25519xsalsa20poly1305. يبدو أن هذا لن يفاجئ أحدا، لكن كود المصدر الخاص بنا مفتوح.
  • تم استبعاد هجوم MITM - كل رسالة عبارة عن معاملة وموقعة بواسطة Ed25519 EdDSA.
  • تنتهي الرسالة في الكتلة الخاصة بها. الاتساق و timestamp لا يمكنك إصلاح الكتل، وبالتالي ترتيب الرسائل.
  • لن تعمل عبارة "لم أقل ذلك" مع الرسائل الموجودة على blockchain.
  • لا توجد بنية مركزية تقوم بالتحقق من "صحة" الرسالة. يتم ذلك من خلال نظام موزع من العقد يعتمد على الإجماع ، وهو مملوك من قبل المستخدمين.
  • استحالة الرقابة - لا يمكن حظر الحسابات ولا يمكن حذف الرسائل.
  • Blockchain 2FA هو بديل للمصادقة الثنائية الجهنمية عبر الرسائل النصية القصيرة، دمر الكثير من الصحة.
  • إن القدرة على الحصول على جميع محادثاتك من أي جهاز وفي أي وقت تعني أنك لست مضطرًا إلى تخزين المحادثات محليًا على الإطلاق.
  • تأكيد تسليم الرسالة. ليس لجهاز المستخدم، ولكن للشبكة. يعد هذا في الأساس تأكيدًا لقدرة المستلم على قراءة رسالتك. هذه ميزة مفيدة لإرسال الإشعارات الهامة.

تشمل فوائد Blockchain أيضًا التكامل الوثيق مع العملات المشفرة Ethereum وDogecoin وLisk وDash وBitcoin (لا تزال هذه العملة قيد التقدم) والقدرة على إرسال الرموز المميزة في الدردشات. لقد قمنا أيضًا بإنشاء مبادل تشفير مدمج.

وبعد ذلك - كيف يعمل كل شيء.

الرسالة هي معاملة

لقد اعتاد الجميع بالفعل على حقيقة أن المعاملات في blockchain تنقل الرموز (العملات المعدنية) من مستخدم إلى آخر. مثل البيتكوين. لقد أنشأنا نوعًا خاصًا من المعاملات لنقل الرسائل.

لإرسال رسالة في برنامج المراسلة على blockchain، عليك اتباع عدة خطوات:

  1. تشفير نص الرسالة
  2. ضع النص المشفر في المعاملة
  3. قم بالتوقيع على الصفقة
  4. إرسال معاملة إلى أي عقدة الشبكة
  5. يحدد نظام العقد الموزع "صحة" الرسالة
  6. إذا كان كل شيء على ما يرام، فسيتم تضمين المعاملة مع الرسالة في الكتلة التالية
  7. يسترد المستلم معاملة الرسالة ويفك تشفيرها

يتم تنفيذ الخطوات من 1 إلى 3 و7 محليًا على العميل، ويتم تنفيذ الخطوات من 5 إلى 6 على الأجهزة المضيفة.

تشفير الرسائل

يتم تشفير الرسالة باستخدام المفتاح الخاص للمرسل والمفتاح العام للمستلم. سنأخذ المفتاح العام من الشبكة، ولكن لهذا، يجب تهيئة حساب المستلم، أي أن يكون لديه معاملة واحدة على الأقل. يمكنك استخدام طلب REST GET /api/accounts/getPublicKey?address={ADAMANT address}، وعند تحميل الدردشات، ستكون المفاتيح العامة للمحاورين متاحة بالفعل.

كيف يعمل برنامج المراسلة اللامركزي على blockchain؟

يقوم برنامج المراسلة بتشفير الرسائل باستخدام خوارزمية Curve25519xsalsa20poly1305 (صندوق كلوريد الصوديوم). نظرًا لأن الحساب يحتوي على مفاتيح Ed25519، لتكوين صندوق، يجب أولاً تحويل المفاتيح إلى Curve25519 Diffie-Hellman.

إليك مثال في جافا سكريبت:

/**
 * 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": "тут будет подпись"
  }
}

توقيع الصفقة

وللتأكد من ثقة الجميع في صحة المرسل والمستلم ووقت الإرسال ومحتوى الرسالة، يتم توقيع المعاملة. يتيح لك التوقيع الرقمي التحقق من صحة المعاملة باستخدام مفتاح عام - وليس هناك حاجة إلى مفتاح خاص لهذا الغرض.

لكن التوقيع نفسه يتم باستخدام المفتاح الخاص:

كيف يعمل برنامج المراسلة اللامركزي على blockchain؟

يوضح الرسم البياني أننا نقوم أولاً بتجزئة المعاملة باستخدام SHA-256 ثم نقوم بتوقيعها Ed25519 إدسا والحصول على التوقيع 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'))
}

إرسال معاملة برسالة إلى عقدة الشبكة

نظرًا لأن الشبكة لا مركزية، فإن أي عقدة ذات واجهة برمجة تطبيقات مفتوحة ستفي بالغرض. تقديم طلب POST إلى نقطة النهاية api/transactions:

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

ردا على ذلك سوف نتلقى معرف المعاملة من هذا النوع

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

التحقق من صحة المعاملة

يحدد نظام العقد الموزع، بناءً على الإجماع، "أصالة" رسالة المعاملة. من ولمن ومتى، هل تم استبدال الرسالة بأخرى، وهل تم تحديد وقت الإرسال بشكل صحيح. هذه ميزة مهمة جدًا لـ blockchain - لا يوجد هيكل مركزي مسؤول عن التحقق، ولا يمكن تزييف تسلسل الرسائل ومحتواها.

أولاً، تتحقق إحدى العقد من الدقة، ثم ترسلها إلى الآخرين - إذا قالت الأغلبية أن كل شيء على ما يرام، فسيتم تضمين المعاملة في الكتلة التالية من السلسلة - وهذا إجماع.

كيف يعمل برنامج المراسلة اللامركزي على blockchain؟

يمكن الاطلاع على جزء كود العقدة المسؤول عن عمليات التحقق على GitHub - Validator.js и Verified.js. نعم، تعمل العقدة على Node.js.

تضمين معاملة مع رسالة في كتلة

إذا تم التوصل إلى توافق في الآراء، فسيتم تضمين المعاملة التي تتضمن رسالتنا في الكتلة التالية إلى جانب المعاملات الصالحة الأخرى.

تحتوي الكتل على تسلسل صارم، ويتم تشكيل كل كتلة لاحقة بناءً على تجزئات الكتل السابقة.

كيف يعمل برنامج المراسلة اللامركزي على blockchain؟

النقطة المهمة هي أن رسالتنا متضمنة أيضًا في هذا التسلسل ولا يمكن "إعادة ترتيبها". إذا وقعت عدة رسائل في كتلة، فسيتم تحديد ترتيبها حسب timestamp رسائل.

قراءة الرسائل

يقوم تطبيق المراسلة باسترداد المعاملات من blockchain التي يتم إرسالها إلى المستلم. لهذا جعلنا نقطة النهاية 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 - تخزين قيمة المفتاح - وهذا نوع آخر من المعاملات asset ليس NaCl-box هو الذي تم تشفيره، ولكن NaCl-secretbox. هذه هي الطريقة التي يقوم بها برنامج المراسلة بتخزين البيانات الأخرى.

لا تزال عمليات نقل الملفات/الصور والمحادثات الجماعية تتطلب الكثير من العمل. بالطبع، في صيغة الخطأ الفادح، يمكن "إفساد" هذا بسرعة، ولكننا نريد الحفاظ على نفس المستوى من الخصوصية.

نعم، لا يزال هناك عمل يتعين القيام به - من الناحية المثالية، تفترض الخصوصية الحقيقية أن المستخدمين لن يتصلوا بعقد الشبكة العامة، ولكنهم سيرفعون عقدهم الخاصة. ما هي النسبة المئوية للمستخدمين الذين تعتقد أنهم يفعلون ذلك؟ هذا صحيح، 0. لقد تمكنا من حل هذه المشكلة جزئيًا باستخدام إصدار Tor من برنامج المراسلة.

لقد أثبتنا إمكانية وجود برنامج مراسلة على blockchain. في السابق، كانت هناك محاولة واحدة فقط في عام 2012 - bitmessage، والذي فشل بسبب طول أوقات تسليم الرسائل، وتحميل وحدة المعالجة المركزية، ونقص تطبيقات الهاتف المحمول.

وترجع الشكوك إلى حقيقة أن برامج المراسلة على blockchain تسبق عصرها - فالناس ليسوا مستعدين لتحمل المسؤولية عن حساباتهم ، وامتلاك المعلومات الشخصية ليس اتجاهًا بعد ، والتكنولوجيا لا تسمح بسرعات عالية على blockchain. سوف تظهر المزيد من نظائرها التكنولوجية لمشروعنا بعد ذلك. سوف ترى.

المصدر: www.habr.com

إضافة تعليق