Anfang 2017 haben wir begonnen, einen Messenger in der Blockchain zu erstellen [Name und Link befinden sich im Profil], indem wir die Vorteile gegenüber klassischen P2P-Messenger erörtert haben.
2.5
Jahre vergingen und wir konnten unser Konzept bestätigen: Instant Messenger-Anwendungen für iOS, Web PWA, Windows, GNU / Linux, Mac OS und Android sind jetzt verfügbar.
Heute werden wir Ihnen sagen, wie der Messenger in der Blockchain angeordnet ist und wie Clientanwendungen mit seiner API arbeiten können.

Wir wollten, dass die Blockchain die Sicherheits- und Datenschutzprobleme klassischer P2P-Messenger löst:
- Ein Klick, um ein Konto zu erstellen - keine Telefone und E-Mails, kein Zugriff auf Adressbücher und Geolokalisierungen.
- Gesprächspartner stellen niemals direkte Verbindungen her, die gesamte Kommunikation erfolgt über ein verteiltes Knotensystem. IP-Adressen von Benutzern sind einander nicht zugänglich.
- Alle Nachrichten sind verschlüsselt. Ende-zu-Ende-Kurve25519xsalsa20poly1305. Es scheint, dass Sie niemanden überraschen werden, aber wir haben Open Source Code.
- MITM-Angriff ist ausgeschlossen - jede Nachricht ist eine Transaktion und wird von Ed25519 EdDSA signiert.
- Die Nachricht fällt in ihren Block. Die Reihenfolge und der
timestamp
Blöcke können nicht festgelegt werden, daher die Reihenfolge der Nachrichten. - "Das habe ich nicht gesagt" funktioniert nicht mit Nachrichten in der Blockchain.
- Es gibt keine zentrale Struktur, die die „Authentizität“ einer Nachricht überprüft. Dies erfolgt durch ein konsensbasiertes verteiltes Knotensystem, das den Benutzern gehört.
- Unmöglichkeit der Zensur - Konten können nicht gesperrt und Nachrichten gelöscht werden.
- Die 2FA-Blockchain ist eine Alternative zu der höllischen 2FA per SMS, die viel Gesundheit gebrochen hat .
- Die Möglichkeit, alle Ihre Dialoge jederzeit von jedem Gerät abzurufen, ist die Möglichkeit, Dialoge überhaupt nicht lokal zu speichern.
- Bestätigung der Nachrichtenübermittlung. Nicht zum Gerät des Benutzers, sondern zum Netzwerk. In der Tat ist dies eine Bestätigung der Fähigkeit des Empfängers, Ihre Nachricht zu lesen. Dies ist eine nützliche Funktion zum Senden kritischer Benachrichtigungen.
Von den Blockchain-Brötchen gibt es auch eine enge Integration mit den Kryptowährungen Ethereum, Dogecoin, Lisk, Dash, Bitcoin (dies ist noch in Bearbeitung) und die Möglichkeit, Token in Chats zu senden. Wir haben sogar einen eingebauten Krypto-Austauscher hergestellt.
Und dann - wie das alles funktioniert.
Nachricht ist eine Transaktion
Jeder ist bereits daran gewöhnt, dass Transaktionen in der Blockchain Token (Münzen) von einem Benutzer auf einen anderen übertragen. Wie Bitcoin. Wir haben eine spezielle Art von Transaktion zum Senden von Nachrichten erstellt.
Um eine Nachricht im Messenger in der Blockchain zu senden, müssen Sie mehrere Schritte durchlaufen:
- Nachrichtentext verschlüsseln
- Setzen Sie den Chiffretext in die Transaktion ein
- Transaktion unterzeichnen
- Senden Sie eine Transaktion an einen beliebigen Host
- Ein verteiltes Knotensystem bestimmt die „Zuverlässigkeit“ einer Nachricht
- Wenn alles in Ordnung ist, wird die Transaktion mit der Nachricht in den nächsten Block aufgenommen.
- Der Empfänger ruft die Nachrichtentransaktion ab und entschlüsselt sie
Die Stufen 1-3 und 7 werden lokal auf dem Client und 5-6 auf den Netzwerkknoten ausgeführt.
Nachrichtenverschlüsselung
Die Nachricht wird mit dem privaten Schlüssel des Absenders und dem öffentlichen Schlüssel des Empfängers verschlüsselt. Wir werden den öffentlichen Schlüssel aus dem Netzwerk nehmen, aber dafür muss das Konto des Empfängers initialisiert werden, dh mindestens eine Transaktion haben. Sie können die REST-Anfrage
GET /api/accounts/getPublicKey?address={ADAMANT address}
. Wenn Sie Chats herunterladen, sind die öffentlichen Schlüssel der Gesprächspartner bereits verfügbar.

Der Messenger verschlüsselt Nachrichten mit dem Algorithmus edge25519xsalsa20poly1305 (
NaCl Box ). Da das Konto Ed25519-Schlüssel enthält, müssen die Schlüssel zunächst in Curve25519 Diffie-Hellman konvertiert werden, um eine Box zu bilden.
Hier ist ein Beispiel in JavaScript:
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) } }
Bildung einer Transaktion mit einer Nachricht
Eine Transaktion hat die folgende allgemeine Struktur:
{ "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": {} }
Für die Transaktionsnachricht ist das
asset
das wichtigste - Sie müssen die Nachricht im
chat
Objekt mit der folgenden Struktur platzieren:
message
- Speichern Sie die verschlüsselte Nachrichtown_message
- noncetype
- Nachrichtentyp
Nachrichten werden auch in Typen unterteilt. Im Wesentlichen gibt der Typparameter an, wie die
message
zu verstehen ist. Sie können nur Text oder ein Objekt mit interessanten Interessen senden. So überträgt der Messenger beispielsweise Kryptowährungen in Chatrooms.
Als Ergebnis bilden wir die Transaktion:
{ "transaction": { "type": 8, "amount": 0, "senderId": "U12499126640447739963", "senderPublicKey": "e9cafb1e7b403c4cf247c94f73ee4cada367fcc130cb3888219a0ba0633230b6", "asset": { "chat": { "message": "cb682accceef92d7cddaaddb787d1184ab5428", "own_message": "e7d8f90ddf7d70efe359c3e4ecfb5ed3802297b248eacbd6", "type": 1 } }, "recipientId": "U15677078342684640219", "timestamp": 63228087, "signature": " " } }
Transaktionssignatur
Damit jeder sicher sein kann, dass der Absender und der Empfänger zum Zeitpunkt des Sendens und des Inhalts der Nachricht authentisch sind, wird die Transaktion signiert. Mit einer digitalen Signatur können Sie die Authentizität einer Transaktion mithilfe eines öffentlichen Schlüssels überprüfen. Ein privater Schlüssel wird hierfür nicht benötigt.
Die Signatur selbst wird jedoch nur vom privaten Schlüssel ausgeführt:

Aus dem Diagramm ist ersichtlich, dass wir zuerst die Transaktion mit SHA-256
hashen, dann Ed25519 EdDSA signieren und die Signatursignatur erhalten und die Transaktionskennung Teil des SHA-256-Hash ist.
Implementierungsbeispiel:
1 - Wir bilden einen Datenblock mit einer Nachricht
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 - Wir betrachten SHA-256 aus dem Datenblock
adamant.getHash = function (trs) { return crypto.createHash('sha256').update(this.getBytes(trs)).digest() }
3 - Wir unterschreiben die Transaktion
adamant.transactionSign = function (trs, keypair) { var hash = this.getHash(trs) return this.sign(hash, keypair).toString('hex') } adamant.sign = function (hash, keypair) { return sodium.crypto_sign_detached(hash, Buffer.from(keypair.privateKey, 'hex')) }
Senden einer Transaktion mit einer Nachricht an einen Host
Da das Netzwerk dezentralisiert ist, reicht jeder Knoten mit einer offenen API aus. Wir stellen eine POST-Anfrage für den Endpunkt
api/transactions
:
curl 'api/transactions' -X POST \ -d 'TX_DATA'
Als Antwort erhalten wir eine Transaktions-ID vom Typ
{ "success": true, "nodeTimestamp": 63228852, "transactionId": "6146865104403680934" }
Transaktionsvalidierung
Ein verteiltes konsensbasiertes Knotensystem bestimmt die „Zuverlässigkeit“ einer Nachrichtentransaktion. Von wem und an wen, wann, ob die Nachricht durch eine andere ersetzt wurde und ob der Zeitpunkt des Sendens korrekt angegeben wurde. Dies ist ein sehr wichtiger Vorteil der Blockchain - es gibt keine zentrale Struktur, die für Überprüfungen verantwortlich ist, und die Reihenfolge der Nachrichten und deren Inhalt kann nicht gefälscht werden.
Zuerst überprüft ein Knoten die Zuverlässigkeit und sendet sie dann an andere. Wenn die meisten sagen, dass alles in Ordnung ist, wird die Transaktion in den nächsten Block der Kette aufgenommen. Dies ist ein Konsens.

Der Teil des Host-Codes, der für die Validierung verantwortlich ist, kann auf GitHub -
validator.js und
verify.js angezeigt werden . Ja, der Knoten läuft auf Node.js.
Transaktion mit Nachricht in Block einschließen
Wenn ein Konsens erzielt wird, fällt die Transaktion mit unserer Nachricht zusammen mit anderen zuverlässigen Transaktionen in den nächsten Block.
Blöcke haben eine strenge Reihenfolge, und jeder nachfolgende Block wird auf der Basis von Hashes vorheriger Blöcke gebildet.

Das Fazit ist, dass unsere Nachricht auch in dieser Sequenz enthalten ist und nicht „neu angeordnet“ werden kann. Wenn mehrere Nachrichten in den Block fallen, wird ihre Reihenfolge durch den
timestamp
Nachrichten bestimmt.
Nachrichten lesen
Die Messenger-Anwendung ruft Transaktionen aus der Blockchain ab, die an den Adressaten gesendet werden. Zu diesem
api/chatrooms
wir den Endpunkt für
api/chatrooms
.
Alle Transaktionen stehen allen zur Verfügung - Sie können verschlüsselte Nachrichten empfangen. Aber nur der Empfänger kann mit seinem privaten Schlüssel und dem öffentlichen Schlüssel des Absenders entschlüsseln:
** * 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) : '' }
Und was noch?
Da Nachrichten auf diese Weise etwa 5 Sekunden lang zugestellt werden - dies ist die Zeit, in der ein neuer Netzwerkblock angezeigt wurde -, haben wir einen Socket-Verbindungs-Client-Knoten und einen Knoten-zu-Knoten entwickelt. Wenn ein Knoten eine neue Transaktion empfängt, überprüft er deren Gültigkeit und überträgt sie an andere Knoten. Die Transaktion steht Messenger-Clients bereits vor dem Einsetzen des Konsenses und der Aufnahme in den Block zur Verfügung. So werden wir sofort Nachrichten übermitteln, ebenso wie die üblichen Boten.
Um das Adressbuch zu speichern, haben wir KVS - Key-Value Storage
erstellt .
Dies ist eine andere Art von Transaktion, bei der ein
asset
nicht mit NaCl-Box, sondern mit
NaCl-Secretbox verschlüsselt wird . Der Messenger speichert also andere Daten.
Datei- / Bildübertragung und Gruppenchats erfordern noch viel Arbeit. Natürlich kann dies im Tyap-Bloop-Format schnell behoben werden, aber wir möchten das gleiche Maß an Privatsphäre gewährleisten.
Ja, es gibt noch viel zu tun - im Idealfall bedeutet echte Privatsphäre, dass Benutzer keine Verbindung zu öffentlichen Netzwerkknoten herstellen, sondern ihre eigenen erhöhen. Was denkst du, wie viele Prozent der Nutzer machen das? Das ist richtig, 0. Teilweise ist es uns gelungen, dieses Problem mit der Tor-Version des Messenger zu lösen.
Wir haben bewiesen, dass ein Messenger in der Blockchain existieren kann. Zuvor gab es 2012 nur einen Versuch -
Bitmessage , der aufgrund der langen Nachrichtenübermittlungszeit, der CPU-Auslastung und des Mangels an mobilen Anwendungen fehlschlug.
Und Skepsis hängt damit zusammen, dass Boten in der Blockchain der Zeit voraus sind - die Menschen sind nicht bereit, Verantwortung für ihr Konto selbst zu übernehmen, der Besitz persönlicher Informationen ist noch kein Trend, und die Technologie erlaubt es nicht, hohe Geschwindigkeiten in der Blockchain sicherzustellen. Im Folgenden werden weitere technologische Analoga unseres Projekts aufgeführt. Du wirst sehen.