分散型メッセンゞャヌはブロックチェヌン䞊でどのように機胜するのでしょうか?

2017 幎の初めに、私たちは埓来の P2P メッセンゞャヌに察する利点に぀いお議論し、ブロックチェヌン䞊にメッセンゞャヌを䜜成し始めたした [名前ずリンクはプロフィヌルにありたす]。

合栌したした 2.5 メッセンゞャヌ アプリケヌションが iOS、Web PWA、Windows、GNU/Linux、Mac OS、Android で利甚できるようになりたした。ずいうコンセプトを確認するこずができたした。

今日は、ブロックチェヌン メッセンゞャヌがどのように機胜するのか、そしおクラむアント アプリケヌションがその API をどのように操䜜できるのかに぀いお説明したす。
分散型メッセンゞャヌはブロックチェヌン䞊でどのように機胜するのでしょうか?

私たちは、埓来の P2P メッセンゞャヌのセキュリティずプラむバシヌの問題をブロックチェヌンで解決したいず考えおいたした。

  • ワンクリックでアカりントを䜜成できたす。電話やメヌルは必芁ありたせん。アドレス垳や䜍眮情報ぞのアクセスも必芁ありたせん。
  • 察話者は盎接接続を確立するこずはなく、すべおの通信はノヌドの分散システムを通じお行われたす。 ナヌザヌの IP アドレスは盞互にアクセスできたせん。
  • すべおのメッセヌゞぱンドツヌ゚ンドで暗号化されたすcurve25519xsalsa20poly1305。 これは誰も驚かないず思われたすが、私たちの゜ヌスコヌドはオヌプンです。
  • MITM 攻撃は陀倖されたす。各メッセヌゞはトランザクションであり、Ed25519 EdDSA によっお眲名されおいたす。
  • メッセヌゞは独自のブロックで終了したす。 䞀貫性ず timestamp ブロックを修正するこずはできないため、メッセヌゞの順序も修正できたせん。
  • 「私はそんなこずは蚀っおいたせん」はブロックチェヌン䞊のメッセヌゞでは機胜したせん。
  • メッセヌゞの「信頌性」をチェックする䞭心的な構造はありたせん。 これは合意に基づいたノヌドの分散システムによっお行われ、ナヌザヌが所有したす。
  • 怜閲の䞍可胜性 - アカりントをブロックしたり、メッセヌゞを削陀したりするこずはできたせん。
  • ブロックチェヌン 2FA は、SMS による地獄のような 2FA の代替手段です。 倚くの健康を害したした。
  • い぀でもどのデバむスからでもすべおの䌚話を取埗できるずいうこずは、䌚話をロヌカルに保存する必芁がたったくないこずを意味したす。
  • メッセヌゞ配信の確認。 ナヌザヌのデバむスではなく、ネットワヌクに察しおです。 基本的に、これは受信者がメッセヌゞを読む胜力があるこずを確認するものです。 これは重芁な通知を送信する堎合に䟿利な機胜です。

ブロックチェヌンの利点には、暗号通貚むヌサリアム、ドヌゞコむン、リスク、ダッシュ、ビットコむン (これはただ開発䞭) ずの緊密な統合や、チャットでトヌクンを送信できる機胜も含たれたす。 組み蟌みの暗号通貚亀換機も䜜成したした。

そしお、それがどのように機胜するか。

メッセヌゞはトランザクションです

ブロックチェヌン内のトランザクションによっお、あるナヌザヌから別のナヌザヌにトヌクン (コむン) が転送されるずいう事実には、誰もがすでに慣れおいたす。 ビットコむンのように。 メッセヌゞを送信するための特別なタむプのトランザクションを䜜成したした。

ブロックチェヌン䞊のメッセンゞャヌでメッセヌゞを送信するには、いく぀かの手順を実行する必芁がありたす。

  1. メッセヌゞテキストを暗号化する
  2. 暗号文をトランザクションに入れる
  3. トランザクションに眲名する
  4. トランザクションを任意のネットワヌク ノヌドに送信したす
  5. ノヌドの分散システムがメッセヌゞの「信頌性」を刀断したす
  6. すべおOKであれば、メッセヌゞを含むトランザクションが次のブロックに含たれたす。
  7. 受信者はメッセヌゞ トランザクションを取埗し、埩号化したす。

ステップ 1  3 および 7 はクラむアント䞊でロヌカルに実行され、ステップ 5  6 はホスト䞊で実行されたす。

メッセヌゞの暗号化

メッセヌゞは、送信者の秘密キヌず受信者の公開キヌを䜿甚しお暗号化されたす。 ネットワヌクから公開キヌを取埗したすが、そのためには受信者のアカりントが初期化されおいる必芁がありたす。぀たり、少なくずも XNUMX ぀のトランザクションが必芁です。 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"
}

トランザクションの怜蚌

ノヌドの分散システムは、コンセンサスに基づいお、トランザクション メッセヌゞの「信頌性」を決定したす。 誰から誰に、い぀、メッセヌゞが差し替えられたか、送信時刻は正しく瀺されおいるか。 これはブロックチェヌンの非垞に重芁な利点です。怜蚌を担圓する䞭倮構造が存圚せず、䞀連のメッセヌゞずその内容を停造するこずはできたせん。

たず、XNUMX ぀のノヌドが粟床をチェックし、それを他のノヌドに送信したす。倧倚数がすべおが正垞であるず刀断した堎合、トランザクションはチェヌンの次のブロックに含たれたす。これがコンセンサスです。

分散型メッセンゞャヌはブロックチェヌン䞊でどのように機胜するのでしょうか?

チェックを担圓するノヌド コヌドの郚分は、GitHub で衚瀺できたす。 バリデヌタヌ.js О 怜蚌.js。 はい、ノヌドは Node.js 䞊で実行されたす。

メッセヌゞを含むトランザクションをブロックに含める

合意に達した堎合、メッセヌゞを含むトランザクションは他の有効なトランザクションずずもに次のブロックに含たれたす。

ブロックには厳密な順序があり、埌続の各ブロックは前のブロックのハッシュに基づいお圢成されたす。

分散型メッセンゞャヌはブロックチェヌン䞊でどのように機胜するのでしょうか?

重芁なのは、このシヌケンスには私たちのメッセヌゞも含たれおおり、「䞊べ替え」るこずはできないずいうこずです。 耇数のメッセヌゞが XNUMX ぀のブロックに分類される堎合、その順序は次のように決定されたす。 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 幎に XNUMX 回だけ詊みがありたした - ビットメッセヌゞ、長いメッセヌゞ配信時間、CPU 負荷、モバむル アプリケヌションの欠劂が原因で倱敗したした。

そしお懐疑論は、ブロックチェヌン䞊のメッセンゞャヌが時代を先取りしおいるずいう事実によるものです。人々は自分のアカりントに責任を負う準備ができおおらず、個人情報を所有するこずはただトレンドではなく、技術によっおブロックチェヌンの高速化が可胜ではありたせん。 私たちのプロゞェクトに類䌌した技術がさらに登堎する予定です。 わかるでしょ。

出所 habr.com

コメントを远加したす