Nan kòmansman 2017, nou te kòmanse kreye yon mesaje sou blockchain la [non ak lyen yo nan pwofil la] lè nou te diskite sou avantaj ki genyen sou mesaje P2P klasik yo.
Pase 2.5 ane, epi nou te kapab pwouve konsèp nou an: aplikasyon mesaje pou iOS, Web PWA, disponib kounye a, Windows, GNU/Linux, Mac OS ak Android.
Jodi a nou pral di w ki jan mesaje blockchain la ap travay ak ki jan aplikasyon kliyan yo ka travay ak API li yo.

Nou te vle blockchain a rezoud pwoblèm sekirite ak konfidansyalite mesaje P2P klasik yo:
- Yon klik pou kreye yon kont - pa gen telefòn oswa imèl, pa gen aksè nan liv adrès oswa jeolokalizasyon.
- Entèrlokuteur yo pa janm etabli koneksyon dirèk; tout kominikasyon fèt atravè yon sistèm distribiye nan nĹuds. Adrès IP itilizatè yo pa aksesib youn ak lòt.
- Tout mesaj yo ankripte fen-a-fen koub25519xsalsa20poly1305. Li sanble ke sa a pa pral sipriz pèsonn, men kòd sous nou an louvri.
- Atak MITM eskli - chak mesaj se yon tranzaksyon epi li siyen pa Ed25519 EdDSA.
- Mesaj la fini nan pwòp blòk li. Konsistans ak
timestampOu pa ka ranje blòk yo, ak Se poutèt sa lòd la nan mesaj yo. - "Mwen pa t 'di sa" pa pral travay ak mesaj sou blockchain la.
- Pa gen okenn estrikti santral ki fè chèk sou "otantisite" nan yon mesaj. Sa a se fè pa yon sistèm distribiye nan nĹuds ki baze sou konsansis, epi li se posede pa itilizatè yo.
- Enposib pou sansi - kont yo pa ka bloke epi mesaj yo pa ka efase.
- Blockchain 2FA se yon altènativ a 2FA infernal via SMS,
- Kapasite pou jwenn tout konvèsasyon ou yo nan nenpòt aparèy nan nenpòt ki lè vle di ou pa bezwen sere konvèsasyon lokalman ditou.
- Konfimasyon livrezon mesaj. Pa nan aparèy itilizatè a, men nan rezo a. Esansyèlman, sa a se konfimasyon kapasite moun k ap resevwa a pou li mesaj ou a. Sa a se yon karakteristik itil pou voye notifikasyon kritik.
Benefis Blockchain gen ladan tou entegrasyon sere ak lajan kript Ethereum, Dogecoin, Lisk, Dash, Bitcoin (yon sèl sa a se toujou nan pwogrè) ak kapasite nan voye marqueur nan chat. Nou menm te fè yon echanjeur kriptografik entegre.
Lè sa a, - ki jan li tout travay.
Yon mesaj se yon tranzaksyon
Tout moun deja abitye ak lefèt ke tranzaksyon yo nan blockchain transfere marqueur (pyès monnen) soti nan yon itilizatè a yon lòt. Tankou Bitcoin. Nou te kreye yon kalite espesyal nan tranzaksyon pou transmèt mesaj.
Pou voye yon mesaj nan yon mesaje sou blockchain a, ou bezwen ale nan plizyè etap:
- Ankripte tèks mesaj la
- Mete chifreman nan yon tranzaksyon
- Siyen tranzaksyon an
- Voye yon tranzaksyon nan nenpòt ne rezo
- Yon sistèm distribiye nan nĹuds detèmine "otantisite" nan yon mesaj
- Si tout bagay se OK, tranzaksyon an ak mesaj la enkli nan pwochen blòk la
- Moun k ap resevwa a rekipere tranzaksyon mesaj la epi li dechifre
Etap 1â3 ak 7 yo fèt lokalman sou kliyan an, epi etap 5â6 yo fèt sou hĂ´tes yo.
Mesaj chifreman
Mesaj la ankode ak kle prive moun k ap voye a ak kle piblik moun k ap resevwa a. Nou pral pran kle piblik la nan rezo a, men pou sa, kont benefisyè a dwe inisyalize, se sa ki, gen omwen yon tranzaksyon. Ou ka itilize yon demann REST GET /api/accounts/getPublicKey?address={ADAMANT address}, epi lè chaje chat, kle piblik entèrlokuteur yo ap deja disponib.

Mesaje a ankripte mesaj yo lè l sèvi avèk algorithm curve25519xsalsa20poly1305 (). Piske kont lan gen kle Ed25519, pou fòme yon bwat, kle yo dwe konvèti an premye nan Curve25519 Diffie-Hellman.
Men yon egzanp nan 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)
}
}Fòme yon tranzaksyon ak yon mesaj
Tranzaksyon an gen estrikti jeneral sa a:
{
"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": {}
} Pou yon tranzaksyon mesaj, bagay ki pi enpòtan se asset - ou bezwen mete yon mesaj nan objè a chat ak estrikti:
message- sove mesaj la chiffresown_message- nonsetype- kalite mesaj
Mesaj yo tou divize an kalite. Esansyèlman, paramèt la type di w kijan pou w konprann message. Ou ka voye jis yon tèks, oswa ou ka voye yon objè ki gen bagay enteresan andedan - pou egzanp, sa a se ki jan mesaje a fè transfè cryptocurrency nan chat.
Kòm yon rezilta, nou kreye yon tranzaksyon:
{
"transaction": {
"type": 8,
"amount": 0,
"senderId": "U12499126640447739963",
"senderPublicKey": "e9cafb1e7b403c4cf247c94f73ee4cada367fcc130cb3888219a0ba0633230b6",
"asset": {
"chat": {
"message": "cb682accceef92d7cddaaddb787d1184ab5428",
"own_message": "e7d8f90ddf7d70efe359c3e4ecfb5ed3802297b248eacbd6",
"type": 1
}
},
"recipientId": "U15677078342684640219",
"timestamp": 63228087,
"signature": "ŃŃŃ ĐąŃĐ´ĐľŃ ĐżĐžĐ´ĐżĐ¸ŃŃ"
}
}Siyati tranzaksyon
Pou asire ke tout moun gen konfyans nan otantisite a nan moun k ap voye a ak moun k ap resevwa a, lè a nan voye a ak kontni an nan mesaj la, tranzaksyon an siyen. Yon siyati dijital pèmèt ou verifye otantisite yon tranzaksyon lè l sèvi avèk yon kle piblik - yon kle prive pa nesesè pou sa.
Men, siyati a li menm fèt ak kle prive a:

Dyagram nan montre ke nou premye hash tranzaksyon an ak SHA-256 epi apre siyen li epi jwenn yon siyati signature, ak ID tranzaksyon an se yon pati nan hash SHA-256 la.
Egzanp aplikasyon:
1 â Fòme yon blòk done, ki gen ladan yon mesaj
/**
* 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 - Konte SHA-256 soti nan blòk done a
/**
* 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 â Siyen tranzaksyon an
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'))
}Voye yon tranzaksyon ak yon mesaj nan yon ne rezo
Depi rezo a desantralize, nenpòt nan nĹuds ki gen yon API ouvè ap fè. Fè yon demann POST nan pwen final la api/transactions:
curl 'api/transactions' -X POST
-d 'TX_DATA'Kòm repons nou pral resevwa yon ID tranzaksyon nan kalite a
{
"success": true,
"nodeTimestamp": 63228852,
"transactionId": "6146865104403680934"
}Validasyon Tranzaksyon
Yon sistèm distribiye nan nĹuds, ki baze sou konsansis, detèmine "otantisite" nan mesaj tranzaksyon an. Nan men ki moun ak ki moun, ki lè, si mesaj la te ranplase ak yon lòt, epi si lè yo te voye a te endike kòrèkteman. Sa a se yon avantaj trè enpòtan nan blockchain la - pa gen okenn estrikti santral ki responsab pou verifikasyon, ak sekans mesaj yo ak kontni yo pa ka fo.
Premyèman, yon sèl ne tcheke presizyon an, ak Lè sa a, voye li bay lòt moun - si majorite a di ke tout bagay se nan lòd, tranzaksyon an pral enkli nan pwochen blòk la nan chèn lan - sa a se konsansis.

Ou ka wè pati nan kòd ne ki responsab chèk yo sou GitHub - и . Wi, ne la kouri sou Node.js.
Ki gen ladan yon tranzaksyon ak yon mesaj nan yon blòk
Si yo rive nan konsansis, tranzaksyon an ak mesaj nou an pral enkli nan pwochen blòk la ansanm ak lòt tranzaksyon valab.
Blòk yo gen yon sekans strik, epi chak blòk ki vin apre yo fòme ki baze sou hash yo nan blòk anvan yo.

Pwen an se ke mesaj nou an tou enkli nan sekans sa a epi yo pa ka "rearanje". Si plizyè mesaj tonbe nan yon blòk, lòd yo pral detèmine pa timestamp mesaj.
Lekti mesaj
Aplikasyon mesaje a rekipere tranzaksyon ki soti nan chèn blòk la ke yo voye bay moun k ap resevwa a. Pou sa nou te fè yon pwen final api/chatrooms.
Tout tranzaksyon yo disponib pou tout moun - ou ka resevwa mesaj chiffres. Men, sèlman moun k ap resevwa a ka dekripte lè l sèvi avèk kle prive li ak kle piblik moun k ap voye a:
**
* 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) : ''
}Ak ki lòt bagay?
Depi mesaj yo delivre nan fason sa a nan apeprè 5 segonn - sa a se tan an yon nouvo blòk rezo parèt - nou te vini ak yon koneksyon kliyan-a-nĹud ak priz nĹud-a-nĹud. Lè yon ne resevwa yon nouvo tranzaksyon, li tcheke validite li epi voye li bay lòt nĹuds. Tranzaksyon an disponib pou kliyan mesaje menm anvan konsansis rive ak enklizyon nan blòk la. Nan fason sa a nou pral delivre mesaj imedyatman, menm jan ak mesaje enstantane regilye.
Pou estoke liv adrès la, nou te fè KVS - Key-Value Storage - sa a se yon lòt kalite tranzaksyon nan ki asset se pa NaCl-box ki chiffres, men . Men ki jan mesaje a estoke lòt done.
Fichye/transfè imaj ak gwoup chat toujou mande anpil travay. Natirèlman, nan fòma bevi-ak-bevi sa a ka "vise moute" byen vit, men nou vle kenbe menm nivo vi prive.
Wi, gen travay toujou pou fèt - depreferans, vi prive reyèl sipoze ke itilizatè yo pa pral konekte nan nĹuds rezo piblik, men yo pral ogmante pwòp yo. Ki pousantaj itilizatè ou panse fè sa? Sa a dwat, 0. Nou te kapab pasyèlman rezoud pwoblèm sa a ak vèsyon an Tor nan mesaje a.
Nou te pwouve ke yon mesaje sou blockchain la ka egziste. Anvan sa, te gen yon sèl tantativ nan 2012 - , ki echwe akòz tan livrezon mesaj long, chaj CPU, ak mank de aplikasyon mobil.
Ak dout se akòz lefèt ke mesaje sou blockchain la devan tan yo - moun yo pa pare yo pran responsablite pou kont yo, posede enfòmasyon pèsonèl se poko yon tandans, ak teknoloji pa pèmèt gwo vitès sou blockchain la. Plis analogue teknolojik nan pwojè nou an ap parèt pwochen. Ou pral wè.
Sous: www.habr.com
