Në fillim të vitit 2017, ne filluam të krijojmë një mesazhues në blockchain [emri dhe lidhja janë në profil] duke diskutuar për Avantazhet përpara mesazhuesve klasikë P2P.
Kaluan 2.5 vjet, dhe arritëm të konfirmojmë konceptin tonë: tani janë të disponueshme aplikacionet e mesazhuesit për iOS, Web PWA, Windows, GNU/Linux, Mac OS dhe Android.
Sot do të flasim për strukturën e mesazhuesit në blockchain dhe si aplikacionet klienti punojnë me API-në e tij.

Donim që blockchain të zgjidhte problemet e sigurisë dhe privatësisë së mesazhuesve klasikë P2P:
- NjĂ« klik pĂ«r tĂ« krijuar njĂ« llogari â asnjĂ« numĂ«r telefoni dhe email, nuk ka qasje nĂ« adresat e kontakteve dhe gjeolokacionet.
- Bashkëbiseduesit kurrë nuk krijojnë lidhje direkte, e gjithë komunikimi kalon përmes një sistemi të shpërndarë nodesh. Adresat IP të përdoruesve nuk janë të aksesueshme nga njëri-tjetri.
- Të gjitha mesazhet janë të koduara End-to-End curve25519xsalsa20poly1305. Në pamje të parë kjo nuk është e habitshme, por ne kemi kodin burimor të hapur.
- Sulmi MITM Ă«shtĂ« i pĂ«rjashtuar â çdo mesazh Ă«shtĂ« njĂ« transaksion dhe nĂ«nshkruhet me Ed25519 EdDSA.
- Mesazhi shkon në bllokun e tij. Rregulli dhe
timestampblloqet nuk mund tĂ« ndryshohen, dhe, pĂ«r pasojĂ«, as rendi i mesazheve. - âNuk e thashĂ« kĂ«tĂ«â nuk do tĂ« funksionojĂ« me mesazhet nĂ« blockchain.
- Nuk ka njĂ« strukturĂ« qendrore qĂ« bĂ«n kontrollin e âbesueshmĂ«risĂ«â sĂ« mesazheve. Kjo bĂ«het nga sistemi i shpĂ«rndarĂ« i nodesh nĂ« bazĂ« tĂ« konsensusit, dhe ai i pĂ«rket pĂ«rdoruesve.
- PamundĂ«sia e censurĂ«s â llogaritĂ« nuk mund tĂ« bllokohen dhe mesazhet nuk mund tĂ« fshihen.
- Blockchain 2FA â njĂ« alternativĂ« ndaj 2FA fatkeq nĂ« SMS,
- MundĂ«sia pĂ«r tĂ« marrĂ« tĂ« gjitha bisedat tuaja nga çdo pajisje nĂ« çdo kohĂ« â kjo Ă«shtĂ« mundĂ«sia pĂ«r tĂ« mos ruajtur bisedat nĂ« mĂ«nyrĂ« lokale fare.
- Konfirmimi i dorëzimit të mesazheve. Jo në pajisjen e përdoruesit, por në rrjet. Në thelb, kjo është konfirmimi i mundësisë së marrësit për të lexuar mesazhin tuaj. Kjo është një veçori e dobishme për dërgimin e njoftimeve kritike.
Si avantazhe të blockchain-it janë gjithashtu integrimi i ngushtë me kriptovalutat Ethereum, Dogecoin, Lisk, Dash, Bitcoin (ky ende është në proces) dhe mundësia për të dërguar tokene në biseda. Ne madje kemi krijuar një shpërndarës kripto të integruar.
Dhe pastaj â si funksionon e gjithĂ« kjo.
Mesazhi është një transaksion.
Të gjithë janë mësuar tashmë se transaksionet në blockchain transferojnë tokene (monedha) nga një përdorues te tjetri. Si tek bitcoin. Ne kemi krijuar një lloj të veçantë transaksionesh për dërgimin e mesazheve.
Për të dërguar një mesazh në mesazherin në blockchain, duhet të kaloni disa etapa:
- Kriptoni tekstin e mesazhit
- Vendosni tekstin e kriptuar në transaksion
- Nënshkruani transaksionin
- Dërgoni transaksionin në çdo nyje të rrjetit
- Sistemi i shpĂ«rndarĂ« i nyjeve pĂ«rcakton âbesueshmĂ«rinĂ«â e mesazhit
- NĂ«se gjithçka Ă«shtĂ« OK â transaksioni me mesazhin pĂ«rfshihet nĂ« bllokun e ardhshĂ«m
- Marrësi nxjerr transaksionin me mesazhin dhe e dekripton
Etapat 1â3 dhe 7 kryhen lokalish nĂ« klient, ndĂ«rsa 5â6 nĂ« nyjet e rrjetit.
Kriptimi i mesazhit
Mesazhi kriptohet me çelĂ«sin privat tĂ« dĂ«rguesit dhe çelĂ«sin publik tĂ« marrĂ«sit. ĂelĂ«si publik do ta marrim nga rrjeti, por pĂ«r kĂ«tĂ« llogaria e marrĂ«sit duhet tĂ« jetĂ« e iniciuar, domethĂ«nĂ«, tĂ« ketĂ« tĂ« paktĂ«n njĂ« transaksion. Mund tĂ« pĂ«rdoret njĂ« kĂ«rkesĂ« REST GET /api/accounts/getPublicKey?address={ADAMANT address}, dhe gjatĂ« ngarkimit tĂ« bisedave çelĂ«sat publikĂ« tĂ« bashkĂ«biseduesve do tĂ« jenĂ« tashmĂ« tĂ« pranishĂ«m.

Mesazheri kripton mesazhet me algoritmin curve25519xsalsa20poly1305 (). Duke pasur parasysh se llogaria përmban çelësa Ed25519, për formimin e box-it më parë çelësat duhet të konvertohen në Curve25519 Diffie-Hellman.
Këtu është një shembull në 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)
}
}Formimi i transaksionit me mesazh
Transaksioni ka një strukturë të tillë të përgjithshme:
{
"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": {}
} PĂ«r transaksionin-mesazh, vlera mĂ« e rĂ«ndĂ«sishme Ă«shtĂ« asset â nĂ« tĂ« duhet tĂ« vendoset mesazhi nĂ« njĂ« objekt bisedĂ« me strukturĂ«n:
messageâ ruajmĂ« mesazhin e kriptuarown_messageâ noncellojiâ tipi i mesazhit
Mesazhet gjithashtu ndahen nĂ« tipe. NĂ« thelb, parametri lloji tregon se si tĂ« kuptohet message. Mund tĂ« dĂ«rgoni thjesht tekst, ose mund tĂ« dĂ«rgoni njĂ« objekt me interesat brenda â pĂ«r shembull, kĂ«shtu mesazheri bĂ«n transferimet e kriptomonedhave nĂ« biseda.
Në fund formojmë transaksionin:
{
"transaction": {
"type": 8,
"amount": 0,
"senderId": "U12499126640447739963",
"senderPublicKey": "e9cafb1e7b403c4cf247c94f73ee4cada367fcc130cb3888219a0ba0633230b6",
"asset": {
"chat": {
"message": "cb682accceef92d7cddaaddb787d1184ab5428",
"own_message": "e7d8f90ddf7d70efe359c3e4ecfb5ed3802297b248eacbd6",
"type": 1
}
},
"recipientId": "U15677078342684640219",
"timestamp": 63228087,
"signature": "këtu do të jetë nënshkrimi"
}
}Nënshkrimi i transaksionit
PĂ«r tĂ« siguruar besueshmĂ«rinĂ« e dĂ«rguesit dhe marrĂ«sit, si dhe kohĂ«n e dĂ«rgimit dhe pĂ«rmbajtjen e mesazhit, transaksioni nĂ«nshkruhet. NĂ«nshkrimi digjital lejon verifikimin e vĂ«rtetĂ«sisĂ« sĂ« transaksionit pĂ«rmes çelĂ«sit publik â çelĂ«si privat nuk Ă«shtĂ« i nevojshĂ«m.
Dhe nënshkrimi vetë realizohet me çelësin privat:

Nga skema duket se fillimisht e hedhim transaksionin nĂ« SHA-256 dhe mĂ« pas e nĂ«nshkruajmĂ« dhe marrim nĂ«nshkrimin nĂ«nshkrim, ndĂ«rsa identifikuesi i transaksionit â Ă«shtĂ« njĂ« pjesĂ« e hashit SHA-256.
Shembuj i implementimit:
1 â FormojmĂ« bllokun e tĂ« dhĂ«nave, duke pĂ«rfshirĂ« mesazhin
/**
* 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 â Llogarisim SHA-256 nga blloku i tĂ« dhĂ«nave
/**
* 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 â NĂ«nshkruajmĂ« transaksionin
adamant.transactionSign = function (trs, keypair) {
var hash = this.getHash(trs)
return this.sign(hash, keypair).toString('hex')
}
/**
* Krijon një nënshkrim bazuar në një hash dhe një çelës çift.
* @implementon {sodium}
* @param {hash} hash
* @param {keypair} keypair
* @return {nënshkrim} nënshkrim
*\/
adamant.sign = function (hash, keypair) {
return sodium.crypto_sign_detached(hash, Buffer.from(keypair.privateKey, 'hex'))
}Dërgimi i transaksionit me mesazh në nodën e rrjetit
Për shkak se rrjeti është i decentralizuar, mund të përdorim çfarëdo nga nodet me API të hapur. Bëjmë kërkesë POST në endpointin api/transactions:
curl 'api/transactions' -X POST
-d 'TX_DATA'Si përgjigje do të marrim ID e transaksionit të tipit
{
"success": true,
"nodeTimestamp": 63228852,
"transactionId": "6146865104403680934"
}Verifikimi i besueshmërisë së transaksionit
Sistemi i shpĂ«rndarĂ« i nodave mbi bazĂ«n e konsensusit pĂ«rcakton "besueshmĂ«rinĂ«" e transaksionit-mesazhit. Nga kush dhe pĂ«r kĂ«, kur, a Ă«shtĂ« zĂ«vendĂ«suar mesazhi me njĂ« tjetĂ«r, dhe a Ă«shtĂ« koha e dĂ«rgimit e saktĂ«. Kjo Ă«shtĂ« njĂ« pĂ«rfitim shumĂ« i rĂ«ndĂ«sishĂ«m i blockchain â nuk ka njĂ« strukturĂ« qendrore, e cila pĂ«rgjegjĂ«se pĂ«r verifikimet, dhe rendi i mesazheve dhe pĂ«rmbajtja e tyre nuk mund tĂ« falsifikohen.
Fillimisht, besueshmĂ«rinĂ« kontrollon njĂ« nod, dhe mĂ« pas e shpĂ«rndan tek tĂ« tjerĂ«t â nĂ«se shumica thonĂ« se gjithçka Ă«shtĂ« nĂ« rregull, transaksioni do tĂ« pĂ«rfshihet nĂ« bllokun e ardhshĂ«m tĂ« zinxhirit â kjo Ă«shtĂ« konsensusi.

NjĂ« pjesĂ« e kodit tĂ« nodit, qĂ« pĂ«rgjigjet pĂ«r verifikimet, mund tĂ« shihet nĂ« GitHub â dhe . Ah, n roja punon nĂ« Node.js.
Përfshijmë transaksionin me mesazh në bllok
Nëse arrihet konsensusi, transaksioni me mesazhin tonë do të kalojë në blokun e ardhshëm së bashku me transaksione të tjera të vlefshme.
Blloqet kanë një renditje të rreptë, dhe çdo bllok tjetër formohet mbi baza të hash-eve të blloqeve të mëparshme.

Thelbi është se mesazhi ynë është gjithashtu i përfshirë në këtë renditje dhe nuk mund të "rregullohet". Nëse në bllok kalojnë disa mesazhe, rendi i tyre do të përcaktohet nga timestamp mesazhet.
Leximi i mesazheve
Aplikacioni-mesazher nxjerr transaksionet nga blockchain-i, të cilat i janë dërguar marrësit. Për këtë kemi krijuar pikën e përshkruar api/chatrooms.
TĂ« gjitha transaksionet janĂ« nĂ« dispozicion pĂ«r çdo njeri â mund tĂ« merren mesazhe tĂ« koduara. Por vetĂ«m marrĂ«si mund ta shqipĂ«rojĂ« atĂ« me çelĂ«sin e tij privat dhe çelĂ«sin publik tĂ« dĂ«rguesit:
**
* 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) : ''
}ĂfarĂ« tjetĂ«r?
Duke pasur parasysh se mesazhet dĂ«rgohen nĂ« kĂ«tĂ« mĂ«nyrĂ« pĂ«r rreth 5 sekonda â koha e shfaqjes sĂ« bllokut tĂ« ri tĂ« rrjetit â ne kemi menduar pĂ«r njĂ« lidhje soket klient-nod dhe nod-nod. Kur nodi merr njĂ« transaksion tĂ« ri, ai kontrollon vlefshmĂ«rinĂ« e tij dhe e kalon te nodet e tjera. Transaksioni Ă«shtĂ« nĂ« dispozicion pĂ«r klientĂ«t-mesazherĂ« edhe para arritjes sĂ« konsensit dhe pĂ«rfshirjes nĂ« bllok. KĂ«shtu do t'i dĂ«rgojmĂ« mesazhet menjĂ«herĂ«, si mesazherĂ«t e zakonshĂ«m.
PĂ«r tĂ« ruajtur librin e adresave, ne krijuam KVS â Ruajtje ĂelĂ«s-VlerĂ« â ky Ă«shtĂ« njĂ« tjetĂ«r tip transaksionesh, nĂ« tĂ« cilat asset nuk kodifikohet NaCl-box, por . KĂ«shtu mesazheri ruan tĂ« dhĂ«na tĂ« tjera.
Transferimi i skedarëve/imazheve dhe bisedat grupore kërkojnë ende shumë punë. Sigurisht, në formatin e shpejtë, mund të "shtohet" shpejt, por ne duam të ruajmë të njëjtin nivel privatësie.
Po, ka ende pĂ«r tĂ« punuar â nĂ« ideale, privatĂ«sia reale nĂ«nkupton qĂ« pĂ«rdoruesit tĂ« mos lidhen me nodet publike tĂ« rrjetit, por tĂ« vendosin tĂ« tyre. A mendoni ju se sa pĂ«rqind e pĂ«rdoruesve e bĂ«jnĂ« kĂ«tĂ«? E saktĂ«, 0. PjesĂ«risht kĂ«tĂ« çështje arritĂ«m ta zgjidhim me versionin Tor tĂ« mesazherit.
Ne provuam qĂ« mesazheri nĂ« blockchain mund tĂ« ekzistojĂ«. MĂ« parĂ« kishte vetĂ«m njĂ« pĂ«rpjekje nĂ« vitin 2012 â , e pasuksesshme pĂ«r shkak tĂ« kohĂ«s sĂ« madhe tĂ« dĂ«rgimit tĂ« mesazheve, ngarkesĂ«s nĂ« procesor dhe mungesĂ«s sĂ« aplikacioneve mobile.
Skepticizmi lidhet me faktin se mesazherĂ«t nĂ« blockchain po e pĂ«rparojnĂ« kohĂ«n â njerĂ«zit nuk janĂ« gati tĂ« marrin pĂ«rgjegjĂ«sinĂ« pĂ«r llogarinĂ« e tyre, pronĂ«sia e informacionit personal nuk Ă«shtĂ« akoma nĂ« modĂ«, dhe teknologjitĂ« nuk mund tĂ« ofrojnĂ« shpejtĂ«si tĂ« larta nĂ« blockchain. Pas kĂ«saj do tĂ« shfaqen analogĂ« mĂ« teknologjikĂ« tĂ« projektit tonĂ«. Do ta shihni.
Burimi: habr.com
