Në fillim të vitit 2017, filluam të krijonim një mesazher në bllok, [emri dhe linku janë në profil] me diskutimin e përfitimeve të tij përpara mesazherëve klasikë P2P.
Kanë kaluar 2.5 vite, dhe arritëm të konfirmojmë konceptin tonë: tani aplikacionet e mesazherit janë të disponueshme për iOS, Web PWA, Windows, GNU/Linux, Mac OS dhe Android.
Sot do të flasim se si funksionon mesazheri në bllok dhe si aplikacionet klientëve punojnë me API-në e tij.

Donim që blloku të zgjidhte problemet e sigurisë dhe privatësisë së mesazherëve klasikë P2P:
- NjĂ« klikim pĂ«r tĂ« krijuar njĂ« llogari â asnjĂ« telefon dhe email, pa akses nĂ« adresarĂ« dhe gjeolokacione.
- Biseduesit kurrë nuk vendosin lidhje të drejtpërdrejta, të gjitha komunikimet kalojnë përmes një sistemi të shpërndarë nyjesh. Adresat IP të përdoruesve nuk janë të visible për njëra-tjetrën.
- Të gjitha mesazhet shifrohen End-to-End me curve25519xsalsa20poly1305. Duket se askush nuk është i befasuar nga kjo, por kodi ynë burimor është i hapur.
- Sulmi MITM Ă«shtĂ« i pĂ«rjashtuar â çdo mesazh Ă«shtĂ« njĂ« transaksion dhe nĂ«nshkruhet me Ed25519 EdDSA.
- Mesazhi kalon në bllokun e tij. Renditja dhe
timestampblloqeve nuk mund tĂ« ndryshohet, 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 verifikimet pĂ«r âvĂ«rtetĂ«sinĂ«â e mesazhit. Kjo bĂ«het nga njĂ« sistem i shpĂ«rndarĂ« nyjesh bazuar nĂ« konsensus, dhe 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 tĂ« tmerrshme pĂ«rmes SMS,
- MundĂ«sia pĂ«r tĂ« marrĂ« tĂ« gjitha bisedat tuaja nga çdo pajisje nĂ« çdo kohĂ« â Ă«shtĂ« mundĂ«sia pĂ«r tĂ« mos e ruajtur bisedat nĂ« mĂ«nyrĂ« lokale fare.
- Konfirmimi i dërgimit të mesazheve. Jo në pajisjen e përdoruesit, por në rrjet. Në thelb, kjo është konfirmimi i aftësisë së merrësit për të lexuar mesazhin tuaj. Kjo është një karakteristikë e dobishme për dërgimin e njoftimeve kritike.
Nga përfitimet e blockchain gjithashtu është integrimi i ngushtë me kriptovalutat Ethereum, Dogecoin, Lisk, Dash, Bitcoin (ky është ende në proces) dhe mundësia për të dërguar tokene në biseda. Ne madje kemi bërë një shkëmbim kripto të integruar.
Dhe tani â si funksionon gjithçka kjo.
Mesazhi është një transaksion.
Të gjithë janë mësuar se transaksionet në blockchain transferojnë tokene (monedha) nga një përdorues te tjetri. Si në rastin e bitcoin-it. Ne kemi krijuar një lloj të veçantë transaksionesh për të transferuar mesazhe.
Për të dërguar një mesazh në një mesazher në blockchain, duhet të kaloni disa hapa:
- TĂ« enkriptohet teksti i mesazhit
- Të vendoset teksti i enkriptuar në transaksion
- Të nënshkruhet transaksioni
- Të dërgohet transaksioni në çdo nyje të rrjetit
- Sistemi i shpërndarë i nyjeve përcakton "vërtetësinë" e mesazhit
- NĂ«se gjithçka Ă«shtĂ« nĂ« rregull â transaksioni me mesazhin pĂ«rfshihet nĂ« blokun e ardhshĂ«m
- Marrësi nxjerr transaksionin me mesazhin dhe e dekripton
Hapat 1â3 dhe 7 realizohen lokal nĂ« klient, ndĂ«rsa 5â6 nĂ« nyjet e rrjetit.
Enkriptimi i mesazhit
Mesazhi enkriptohet 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 inicializuar, domethĂ«nĂ« tĂ« ketĂ« tĂ« paktĂ«n njĂ« transaksion. Mund tĂ« pĂ«rdorni 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Ă« nĂ« dispozicion.

Mesazhi kodon mesazhët me algoritmin curve25519xsalsa20poly1305 (). Duke qenë se llogaria përmban çelësi Ed25519, për të formuar box-in, çelësat duhet së pari të konvertohen në Curve25519 Diffie-Hellman.
Ja 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 mesazhin
Transaksioni ka këtë strukturë 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Ă« objektin chat me strukturĂ«n:
messageâ ruajmĂ« mesazhin e enkriptuarown_messageâ noncetypeâ tipi i mesazhit
Mesazhet gjithashtu ndahet nĂ« tipe. NĂ« thelb, parametri type njofton 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 transfertat e kriptovalutave nĂ« biseda.
Si 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": "të këtu do të jetë nënshkrimi"
}
}Nënshkrimi i transaksionit
PĂ«r tĂ« siguruar qĂ« çdo person ta ketĂ« origjinalitetin e dĂ«rguesit dhe marrĂ«sit, momentin e dĂ«rgimit dhe pĂ«rmbajtjen e mesazhit, transaksioni nĂ«nshkruhet. NĂ«nshkrimi digjital lejon verifikimin e saktĂ«sisĂ« sĂ« transaksionit pĂ«rmes çelĂ«sit publik â çelĂ«si privat nuk Ă«shtĂ« i nevojshĂ«m pĂ«r kĂ«tĂ«.
Nënshkrimi vetë kryhet me çelësin privat:

Nga skema shihet, se transaksioni fillimisht është hashuar me SHA-256, dhe pastaj nënshkruhet dhe marrim nënshkrimin nënshkrim, ndërsa identifikuesi i transaksionit është një pjesë e hash-it SHA-256.
Shembulli i realizimit:
1 â FormojmĂ« blok tĂ« dhĂ«nash, 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 bloku 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 të bazuar në një hash dhe një çift çelësash.
* @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'))
}Dërgimi i transaksionit me një mesazh në nyjën e rrjetit
Duke qenë se rrjeti është decentralizuar, çdo një nga nyjat me API të hapur do të funksiononte. Bëjmë një kërkesë POST në fundpunktin api/transactions:
curl 'api/transactions' -X POST
-d 'TX_DATA'Në përgjigje do të marrim ID-në e transaksionit të tipit
{
"success": true,
"nodeTimestamp": 63228852,
"transactionId": "6146865104403680934"
}Kontrolli i vërtetësisë së transaksionit
NjĂ« sistem i shpĂ«rndarĂ« i nyjave tĂ« bazuara nĂ« konsensus pĂ«rcakton "vĂ«rtetĂ«sinĂ«" e transaksionit-mesazh. Nga kush dhe kujt, kur, a Ă«shtĂ« zĂ«vendĂ«suar mesazhi me ndonjĂ« tjetĂ«r, a Ă«shtĂ« koha e dĂ«rgimit e saktĂ«. Kjo Ă«shtĂ« njĂ« pĂ«rparĂ«si shumĂ« e rĂ«ndĂ«sishme e blockchain-it â nuk ka njĂ« strukturĂ« qendrore qĂ« Ă«shtĂ« pĂ«rgjegjĂ«se pĂ«r kontrollin, dhe sekuenca e mesazheve dhe pĂ«rmbajtja e tyre nuk mund tĂ« manipulohen.
Fillimisht, njĂ« nyje kontrollon vĂ«rtetĂ«sinĂ«, pastaj e shpĂ«rndan te 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.

Pjesa e kodit tĂ« nyjĂ«s qĂ« Ă«shtĂ« pĂ«rgjegjĂ«se pĂ«r verifikimet mund tĂ« shikohet nĂ« GitHub â dhe . Po, nyja funksionon me Node.js.
Aktivizojmë transaksionin me mesazhin në bllok
Nëse arrihet konsensusi, transaksioni me mesazhin tonë do të regjistrohet në bllokun e ardhshëm së bashku me transaksionet e tjera të besueshme.
Blloket kanë një rend të rreptë, dhe çdo bllok pasues formohet mbi bazën e hash-eve të bllokeve të mëparshme.

Thelbi është që mesazhi ynë gjithashtu është i përfshirë në këtë rend dhe nuk mund të "rregullohet". Nëse disa mesazhe hyjnë në bllok, rendi i tyre do të përcaktohet nga timestamp mesazheve.
Leximi i mesazheve
Aplikacioni i mesazheve nxjerr transaksionet nga bllokçeni që u dërgohen pranuesit. Për këtë, kemi bërë një pikë përfundimtare api/chatrooms.
TĂ« gjithĂ« transaksionet janĂ« tĂ« disponueshme pĂ«r secilin â mund tĂ« marrin mesazhe tĂ« koduara. Por vetĂ«m pranuesi mund t'i dekriptojĂ« 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 mesazhet shpĂ«rndahen nĂ« rreth 5 sekonda â ky Ă«shtĂ« koha e shfaqjes sĂ« njĂ« blloku tĂ« ri nĂ« rrjet â ne krijuam njĂ« lidhje socket klient-nod dhe nod-nod. Kur nodi merr njĂ« transaksion tĂ« ri, verifica validitetin e tij dhe e dĂ«rgon te nodet e tjera. Transaksioni Ă«shtĂ« i disponueshĂ«m pĂ«r klientĂ«t-messenger edhe para se tĂ« arrihej konsensusi dhe tĂ« pĂ«rfshihej nĂ« bllok. KĂ«shtu do tĂ« dĂ«rgojmĂ« mesazhe nĂ« mĂ«nyrĂ« momentale, ashtu siç bĂ«jnĂ« messengerat e zakonshĂ«m.
PĂ«r tĂ« ruajtur librin e kontakteve, ne krijuam KVS â Key-Value Storage â ky Ă«shtĂ« njĂ« tjetĂ«r lloj transaksionesh, nĂ« tĂ« cilat asset kriptografia nuk Ă«shtĂ« NaCl-box, por . KĂ«shtu messengeri ruan dhe tĂ« dhĂ«na tĂ« tjera.
Transferimi i skedarĂ«ve/imazheve dhe bisedat grupore kĂ«rkojnĂ« ende shumĂ« punĂ«. Sigurisht, nĂ« formatin e bĂ«rĂ« shpejt, kjo mund tĂ« âshtohetâ shpejt, por ne duam tĂ« ruajmĂ« tĂ« njĂ«jtin nivel privatĂ«sie.
Po, ka ende shumĂ« pĂ«r tĂ« punuar â nĂ« mĂ«nyrĂ« ideale, privatĂ«sia reale nĂ«nkupton qĂ« pĂ«rdoruesit nuk do tĂ« lidhen me nodet publike tĂ« rrjetit, por do t'i ngrinin ato tĂ« veta. Si mendoni, sa pĂ«rqind e pĂ«rdoruesve e bĂ«jnĂ« kĂ«tĂ«? E saktĂ«, 0. PjesĂ«risht ky problem na Ă«shtĂ« zgjidhur me versionin Tor tĂ« messenger-it.
Ne kemi dĂ«shmuar se njĂ« mesazher mbi blockchain mund tĂ« ekzistojĂ«. Deri mĂ« tani ka pasur vetĂ«m njĂ« pĂ«rpjekje nĂ« vitin 2012 â , e cila dĂ«shtoi pĂ«r shkak tĂ« kohĂ«s sĂ« madhe tĂ« dorĂ«zimit tĂ« mesazheve, ngarkesĂ«s sĂ« procesorit dhe mungesĂ«s sĂ« aplikacioneve celularĂ«.
Dhe skepsizmi lidhet me faktin se mesazherĂ«t mbi blockchain janĂ« pĂ«rpara kohĂ«s â njerĂ«zit nuk janĂ« gati tĂ« marrin pĂ«rgjegjĂ«sinĂ« pĂ«r llogarinĂ« e tyre, zotĂ«rimi i informacionit personal nuk Ă«shtĂ« akoma nĂ« modĂ«, dhe teknologjitĂ« nuk kanĂ« aftĂ«sinĂ« tĂ« ofrojnĂ« shpejtĂ«si tĂ« larta mbi blockchain. Pas nesh do tĂ« shfaqen alternativa mĂ« teknologjike tĂ« projektit tonĂ«. Do ta shihni.
Burimi: habr.com
