În dezvoltare — încă nu e publicat în magazinele de aplicații
Mesaje pe care nimeni altcineva nu le poate citi.
Invictus este un chat criptat cap la cap. Criptarea se face pe telefon, cu libsignal — același protocol Signal, cu schimb de chei rezistent la calculatoare cuantice. Serverul transportă octeți pe care nu îi poate deschide.
Cont fără număr de telefon și fără adresă de e-mail. Clientul Android e testat pe dispozitive reale; cel de iOS e scris, dar încă nu poate primi mesaje cu aplicația închisă.
Pentru cine e
Dacă ai un motiv întemeiat să nu-ți dai numărul de telefon
Invictus e pentru oamenii pentru care „n-am nimic de ascuns" nu e un răspuns: un ziarist și sursa lui, un medic și pacientul, un avocat și clientul, doi oameni care fac o afacere și nu vor ca legătura dintre ei să fie a treia parte. Nu e o aplicație pentru toată lumea, și nu încearcă să fie.
| Întrebare | Aplicația obișnuită | Invictus |
|---|---|---|
| Ce dai ca să-ți faci cont? | Cele mai multe cer un număr de telefon, deci o identitate. | Un nume ales de tine și o pereche de chei. Fără telefon, fără e-mail, fără parolă. |
| Cine ține cheile? | Variază, iar acolo unde nu e criptare cap la cap, serverul le poate deriva. | Telefonul tău. Cheia care deschide mesajele nu ajunge niciodată pe server. |
| Numele grupului, numele tău afișat, poza? | De regulă câmpuri în baza de date a serviciului. | Criptate cap la cap. În baza de date a serverului nu există câmp pentru ele. |
| Cât timp stau mesajele pe server? | Cât ține politica serviciului. | Până la confirmarea livrării; apoi rândul se șterge. Cele nelivrate expiră. |
| Cum plătești? | Card sau magazinul de aplicații, deci un nume. | Stablecoin, dintr-un portofel care e al tău. Preț implicit 5 $ pe lună. |
Începe cu ce nu poate face. Cea mai utilă pagină de aici nu e lista de funcții, ci lista limitelor — ce nu apără Invictus, scris pe față, cu motivul. Dacă după ea tot ți se pare că-ți trebuie, atunci chiar îți trebuie. O aplicație de securitate care te lasă să afli singur unde se termină protecția te-a pus deja în pericol.
Criptare
libsignal, cu chei rezistente la cuantic
Invictus nu are un protocol propriu. Folosește libsignal 0.86.5,
biblioteca lui Signal: PQXDH pentru stabilirea sesiunii — schimb de chei
clasic combinat cu Kyber-1024, ca o înregistrare de trafic de azi să nu
poată fi descifrată mâine de un calculator cuantic — și Double Ratchet
pentru mesaje, deci fiecare mesaj are cheia lui. În grupuri se folosesc
sender keys, rotite la fiecare schimbare de membri.
Cheia de dispozitiv
ECDSA P-256 · în hardwareTrăiește în Android Keystore / StrongBox și nu poate fi exportată. Autentifică telefonul la server. Nu iese niciodată din elementul securizat.
Identitatea Signal
Curve25519Identitatea de mesagerie, cea care intră în sesiunile Double Ratchet.
Cheia de cont
ECDSA P-256 · portabilăSemnează fiecare dispozitiv al tău. Clientul verifică semnătura înainte să deschidă o sesiune — asta e apărarea împotriva unui server care ar inventa un dispozitiv nou pe contul tău.
Identificatori care se verifică singuri
ID-ul de contact INVC-… este un hash SHA-256 al cheii tale
de cont. Doi oameni care compară ID-uri compară chei, nu nume alese de
server. În plus, fiecare conversație are un număr de siguranță de 60 de
cifre, identic pe ambele telefoane.
Registru de chei verificabil
Serverul ține un jurnal Merkle append-only al cheilor publice, cu vârf semnat Ed25519. Clientul verifică semnătura și dovada de incluziune și se asigură că cheia dovedită e chiar cea primită — un server care răspunde cu o cheie și dovedește alta este prins.
Funcții
Ce face aplicația
Totul de mai jos există în clientul Android. Unde o funcție e făcută doar pe jumătate, scrie chiar acolo; restul lucrurilor neterminate sunt strânse în secțiunea de stare, la sfârșit.
Cont fără număr de telefon
Nu ți se cere niciun SMS și nicio adresă de e-mail, iar parolă nu există. Contul e un nume de utilizator ales de tine plus o pereche de chei, iar autentificarea înseamnă semnarea unui nonce trimis de server. Nu există hash de parolă care să se poată scurge.
Mesaje efemere
Un temporizator per conversație, sincronizat între telefoane prin canalul criptat. E pornit din start, cu o săptămână implicit: o funcție de siguranță pe care trebuie să o descoperi și să o pornești nu apără pe nimeni.
Ștergerea scoate rândul din baza de date locală, nu îl ascunde din interfață, și curăță și previzualizarea din lista de conversații. În grupuri temporizatorul e deocamdată local: îl schimbi la tine, nu la ceilalți.
Apeluri criptate
Voce și video peste WebRTC: media e criptată cu DTLS-SRTP, iar negocierea trece tot prin canalul criptat cap la cap — un server care ar putea rescrie amprentele SDP s-ar putea altfel așeza la mijloc.
Pe Android, un serviciu de prim-plan face telefonul să sune și cu ecranul stins. Pe iPhone asta încă nu funcționează.
Mai multe telefoane, un cont
Poți lega un al doilea dispozitiv, tastând un cod scurt de pe telefonul nou pe cel vechi. Legarea cere cheia de cont, nu doar o sesiune activă: un token de acces furat nu poate atașa un dispozitiv străin. Fiecare dispozitiv nou e semnat de cheia de cont, iar ceilalți verifică semnătura.
Deocamdată incomplet: telefonul legat primește mesajele de grup, dar conversațiile 1 la 1 merg tot către un singur dispozitiv, iar istoricul nu se transferă. Sincronizarea completă între dispozitive nu e gata.
Grupuri
Numele grupului e criptat — serverul nu are câmp pentru el. Când cineva e scos, epoca grupului crește și clienții generează o cheie nouă de trimitere; altfel excluderea ar fi cosmetică, fostul membru rămânând cu cheia veche.
Atașamente
Fiecare fișier primește o cheie proprie de 32 de octeți și e criptat AES-256-GCM pe telefon. Serverul primește numai octeți sigilați; cheia călătorește prin canalul criptat.
Cod de acces și amprentă
Datele de pe telefon sunt criptate valoare cu valoare, sub o cheie ținută în Keystore. Cu blocarea aplicației pornită, cheia e învelită sub o cheie Keystore care cere autentificare biometrică la fiecare folosire — nu o fereastră de valabilitate.
O amprentă înrolată de altcineva distruge cheia în loc să deschidă ușa.
Seif — copie de siguranță a cheilor
Cheia de cont poate fi salvată într-un seif sigilat cu o parolă de-a ta: Argon2id (minim impus de server) plus AES-256-GCM. O parolă greșită nu produce text aiurea, ci eșuează la verificarea etichetei GCM.
Seiful păstrează doar cheia contului — atât cât să-ți recapeți identitatea pe un telefon nou. Mesajele și fișierele nu sunt salvate nicăieri; dacă pierzi telefonul, pierzi conversațiile.
Cod de constrângere
Un al doilea cod care, la introducere, distruge cheile din Keystore și golește stocarea locală înainte de a raporta succes. Pe disc, cele două coduri sunt indistinctibile: nimic nu trădează că există un al doilea.
Serverul
Un releu, nu o arhivă
Serverul e un singur binar Go, cu PostgreSQL, fără Docker și fără dependențe la rulare. Nu decide nimic despre conținut, pentru că nu îl poate vedea. Merită spus și ce vede totuși: ascunderea unei părți din metadate e inerentă oricărui sistem care rutează mesaje.
Ce nu poate citi serverul
- Conținutul mesajelor — criptate înainte să plece de pe telefon.
- Atașamentele — încărcate deja sigilate, cu cheie per fișier.
- Numele grupurilor — nu există câmp pentru ele în bază.
- Numele afișat și poza de profil — călătoresc cap la cap, ca orice mesaj.
- Copiile de siguranță ale cheilor — sigilate cu parola ta.
Fără parole
Un cont e o pereche de chei. Nu există nimic de refolosit de pe alt site și niciun hash de parolă care să se scurgă.
Jetoane Ed25519, nu JWT
Formatul fixează algoritmul. Agilitatea JWT — alg:none,
confuzia HS256/RS256 — a produs un șir lung de ocoliri de autentificare.
Revocare imediată
Sesiunea e verificată la fiecare cerere. Delogarea sau revocarea unui dispozitiv invalidează pe loc jetoanele deja emise, nu la expirare.
Jetoane de reîmprospătare rotite
Dacă unul e furat și folosit, următoarea reîmprospătare a clientului legitim eșuează: furtul iese la suprafață în loc să treacă neobservat.
Livrat înseamnă șters
Mesajele livrate se șterg la confirmare; cele nelivrate expiră. Stocarea e mărginită de politică, nu de folosință.
Înregistrare pe bază de invitație
Implicit închisă. Codul se generează pe server și se afișează o singură dată; în bază se păstrează doar hash-ul lui.
Portofel și abonament
Plata fără să treci printr-un nume
Un cont care nu cere număr de telefon n-ar avea niciun rost dacă plata ar cere un card pe numele tău. De aceea abonamentul se plătește în cripto, iar aplicația are un portofel propriu pe telefon.
Portofel self-custodial, pe telefon
Cheile sunt generate pe dispozitiv dintr-o sămânță BIP-39 și derivate BIP-32/BIP-44. Sămânța nu pleacă nicăieri: e ținută criptată sub o cheie din Android Keystore, deblocată cu amprentă la fiecare semnare. Serverul nu o vede și nu o poate recupera. Pe un telefon fără amprentă înrolată protecția scade la codul aplicației, iar ecranul portofelului ți-o spune direct.
Fraza de recuperare e singura copie: nu există nimeni de la care să o ceri înapoi. Asta înseamnă self-custodial.
Poți primi și trimite: adresă cu cod QR, iar la trimitere semnarea se face pe telefon, cu cheia derivată în acel moment și nepăstrată după aceea — fiecare operație cere amprenta din nou. Pe Tron se vede și istoricul mișcărilor; pe Base nu, fiindcă nodurile publice refuză căutările prin istorie — iar o listă goală ar fi părut că n-ai făcut nimic.
Înainte de prima întrebare pusă unui nod public, aplicația îți cere voie o dată și ține minte răspunsul. Nodul acela vede și adresa ta, și adresa ta de internet. Nu întrebăm niciun serviciu de prețuri: cifra în dolari presupune că un stablecoin face un dolar.
Abonament lunar, în stablecoin
Prețul implicit e de 5 $ pe lună, plătit în USDC pe rețeaua Base sau în USDT pe Tron. Conturile noi au o perioadă de probă de șapte zile.
Serverul nu are chei și nu semnează nimic: doar întreabă un nod public cât a ajuns la adresa de depunere a facturii. Chiar dacă nodul l-ar minți, cel mai rău lucru care se poate întâmpla e un abonament dat degeaba — n-are ce lua.
Base USDC Tron USDT Probă 7 zile Preț implicit 5 $ / lună
Un lucru pe care nu vreau să-l ascund: ca să afle dacă o factură a fost plătită, serverul întreabă un nod public al lanțului. Acel furnizor vede adresele de depunere și adresa IP a serverului — exact categoria de metadate pe care restul aplicației le evită. Cu un nod propriu dispare, dar asta e o alegere de operare, nu ceva ce poate rezolva codul.
Cerința de abonament este oprită implicit pe server; un operator o pornește când e pregătit. Când e pornită și abonamentul expiră, poți primi mesaje în continuare, dar nu mai poți trimite.
Portofelul și abonamentul sunt încă două ecrane separate: plata se face copiind adresa facturii în formularul de trimitere. Nu există încă un buton „plătește din portofel”.
Taxa de rețea se plătește în moneda lanțului, nu în stablecoin — ai nevoie de puțin TRX pe Tron sau de puțin ETH pe Base, altfel trimiterea nu pleacă. Aplicația ți-o spune în fereastra de confirmare, împreună cu adresa întreagă a destinatarului.
Escrow
Bani ținuți fără să-i ținem noi
Doi oameni care nu se cunosc vor să facă un schimb: unul dă bani, altul dă un lucru, și fiecare se teme că celălalt dispare după ce primește primul. Escrow-ul rupe simultaneitatea asta. Partea grea nu e să ții banii, ci să-i ții fără să devii tu însuți riscul.
Două semnături din trei
Fiecare tranzacție primește o adresă Tron ale cărei permisiuni sunt împărțite între trei chei — cumpărător, vânzător, serviciu — cu pragul doi. Când schimbul merge bine, cei doi semnează și banii pleacă: serviciul nici nu află că tranzacția a existat.
Dacă unul dispare, celălalt poate semna împreună cu arbitrul. Iar dacă serviciul dispare sau devine ostil, cei doi închid tranzacția fără el. Serviciul singur nu poate face nimic: nu poate lua banii și nu poate bloca o înțelegere.
Nimic nou de pus la păstrare
Cheia fiecărei tranzacții se derivă din aceeași frază de recuperare pe care o ai deja scrisă pe hârtie, pe o ramură separată a arborelui. Nu apare o a doua copie de siguranță de făcut și nici una de uitat, iar un telefon pierdut în mijlocul unui schimb nu pierde banii din escrow.
Câte o cheie per tranzacție, nu una refolosită: pe un lanț public, o adresă refolosită leagă între ele toate afacerile tale, la vedere. Cheia portofelului obișnuit nu se atinge deloc.
Verificarea care contează cel mai mult. Trecerea contului în doi-din-trei o face cumpărătorul — adică exact cel care nu are de pierdut dacă o face prost. De aceea vânzătorul o verifică singur, pe lanț, înainte să livreze ceva, iar aplicația nu-i arată butonul „Am livrat" până nu s-a uitat: în locul lui stă „Verifică contul", cu avertismentul că, dacă permisiunile au rămas la cumpărător, acesta poate retrage banii în clipa în care coletul a plecat.
Verificarea nu se uită doar la permisiunea de proprietar, ci la toate permisiunile active, și respinge și capcanele care arată bine la prima vedere: aceeași cheie trecută de două ori, o cheie cu pondere cât pragul (deci care semnează singură), sau ponderi care nu ajung la prag — caz în care banii ar rămâne blocați pentru totdeauna.
Ce se decide din fapte, fără să judece nimeni
Termenii — ce se vinde, pe cât, în cât timp — călătoresc criptați cap la cap între cei doi, ca orice mesaj, și sunt semnați de amândoi printr-o amprentă a înțelegerii. Cele mai multe situații se rezolvă apoi din fapte pe care oricine le poate citi: câți bani au intrat la adresă, ce oră e, ce a semnat fiecare. Aceleași fapte dau același rezultat, oricine ar rula codul.
| Situația | Rezultatul |
|---|---|
| Cumpărătorul confirmă primirea | Banii merg la vânzător. E cea mai puternică declarație din tot sistemul — omul care riscă banii vorbește în favoarea celuilalt — și nimic n-o răstoarnă, nici măcar un termen expirat. |
| Banii n-au intrat până la termen | Înțelegerea cade și banii se întorc. O sumă parțială nu ține loc de finanțare: un escrow pe jumătate plătit e o capcană pentru vânzător. |
| Vânzătorul n-a anunțat livrarea până la termen | Banii se întorc la cumpărător. Nu fiindcă vânzătorul ar fi vinovat, ci fiindcă banii nu rămân blocați pentru o livrare care n-a fost nici măcar anunțată. |
| Livrare anunțată, dar cumpărătorul tace | Trece la arbitru — nu se eliberează automat. Tăcerea poate însemna și „n-a venit nimic", așa că aici nu decide ceasul. |
| Cineva deschide o dispută | Ceasurile se opresc și decide arbitrul. Altfel, cine deschide o dispută cu o oră înainte de expirare ar pierde prin simpla trecere a timpului. |
Arbitrul: ce poate și ce nu poate însemna „imparțial"
Un bot nu e imparțial fiindcă e bot. Cine îi scrie regulile decide rezultatele, iar dacă rulează pe serverul nostru, imparțialitatea lui e imparțialitatea noastră. A-i spune „bot" nu scoate încrederea din ecuație, doar o ascunde. Ce se poate construi cu adevărat sunt patru lucruri:
Judecata rămâne excepția
Regulile de mai sus acoperă cazurile obișnuite fără nicio judecată. Partea aceea e deterministă, și e singura care poate fi numită imparțială fără ghilimele. Fiecare caz rezolvat acolo e un caz în care nimeni n-are nevoie de bunăvoința noastră.
Regulile se fixează înainte
Termenele, ce se întâmplă la tăcere, cine plătește taxele — toate se arată și se acceptă înainte ca banii să intre, și intră în amprenta pe care o semnează amândoi. Un arbitru care își află regulile odată cu cazul nu e arbitru, e o părere.
Dovezile sunt date, nu instrucțiuni
Ambele părți vor să câștige și amândouă scriu textul pe care arbitrul îl citește. Dovezile intră structurat — sumă, dată, cod de expediere, hash de tranzacție — iar ce nu încape în structură e etichetat ca text scris de o parte interesată. Regulile nu pot fi rescrise de conținutul cazului.
Modelul nu semnează niciodată
Propune un rezultat; codul îl verifică din nou pe faptele obiective înainte să se semneze ceva, și respinge o decizie fără motivare sau sprijinită pe un fapt care nu e în dosar. Există două rezultate posibile, nu sume parțiale — un arbitru care poate propune orice cifră poate fi argumentat spre oricare.
Ce rămâne imposibil, și nu se poate rezolva cu mai mult cod: niciun program nu poate ști dacă lucrul vândut era cel din anunț, dacă a ajuns întreg sau dacă fotografia e de azi. Escrow-ul ține banii; adevărul îl spun oamenii. Arbitrul poate fi consecvent — aceleași dovezi, același rezultat — nu atoateștiutor. Cine spune că un bot se asigură că nu vă păcăliți vinde ceva.
Comisionul stă scris în înțelegerea pe care o semnează amândoi și se scade din suma eliberată — nu e luat de noi din afară, fiindcă pe drumul normal noi nici nu aflăm de tranzacție. Procentul se configurează și e zero implicit, deci nu găsești o cifră aici. Urmarea, spusă limpede: doi oameni cu aplicații modificate care se înțeleg între ei pot să nu-l plătească deloc.
Limite
Ce nu protejează Invictus
Scris aici ca să nu descopere nimeni pe cont propriu, la un moment prost. O aplicație de securitate care promite mai mult decât livrează e mai periculoasă decât una care nu promite nimic.
| Nu apără de | De ce |
|---|---|
| Capturi de ecran și fotografii | Celălalt telefon are textul în clar. „Șterge la amândoi” există, dar e o cerere, nu o garanție: o aplicație modificată o poate ignora, iar aplicația spune asta chiar acolo unde apeși. |
| Un telefon compromis | Un program rău-intenționat cu drepturile aplicației, pe un telefon deblocat, vede exact ce vede utilizatorul. |
| Furnizorul de găzduire, cât timp serverul rulează | Criptarea discului apără discul oprit. Cheia stă în memorie, iar cine controlează hipervizorul o poate citi. |
| Analiza de trafic | Momentul și mărimea plicurilor sunt vizibile pentru server și pentru oricine urmărește rețeaua. |
| Un telefon confiscat în timp ce aplicația rulează | Legarea de amprentă e per pornire de proces, nu per blocare de ecran. Alternativa ar fi un telefon blocat care nu poate suna la un apel primit — o alegere luată deliberat în cealaltă direcție. |
| Un server care arată un registru de chei diferit fiecărui utilizator | Clientul verifică azi doar că o cheie chiar se află în jurnal. Nu compară vârfurile jurnalului între ei — deci un server care ține două jurnale paralele nu e încă detectat. |
| Un adversar care copiază telefonul înainte să ceară codul | Codul de constrângere șterge datele la introducere. Împotriva unei imagini făcute mai devreme nu ajută nimic, pe niciun telefon. |
Invictus nu a trecut printr-un audit de securitate extern. Nu există certificări și nu există cifre de utilizatori de arătat. Ce există e codul, testele lui și un document de model de securitate scris pentru cineva care vrea să-l atace, nu pentru cineva căruia i se vinde.
Stare
Unde e proiectul acum
Invictus e în dezvoltare. Nu e publicat în magazinele de aplicații și nu are încă o instanță publică la care să te poți înscrie.
- Merge Clientul Android Înregistrare, conversații 1:1 și de grup, livrare în timp real prin WebSocket, atașamente, seif și blocare cu cod, verificarea registrului de chei și numere de siguranță, apeluri voce și video. Testat pe dispozitive reale.
- Merge Serverul Binar Go cu PostgreSQL, migrări incluse, limitare de rată, registru de chei, abonamente. Suita de teste rulează criptografie reală, nu simulacre.
- Parțial Clientul iOS Există și acoperă aceleași funcții: înregistrare, conversații, grupuri, seif, blocare cu Face ID, apeluri. Îi lipsesc însă integrarea cu sistemul pentru apeluri și notificările push, deci un iPhone blocat nu sună și nu primește mesaje cu aplicația închisă. Nu e publicat.
- Parțial Sincronizare între dispozitivele tale Legarea unui al doilea telefon funcționează, dar mesajele 1 la 1 ajung într-un singur loc și istoricul nu se mută. Până se termină, tratează al doilea telefon ca pe unul secundar, nu ca pe o copie.
- Ține de instalare Apeluri între rețele diferite Codul de releu TURN și scriptul de instalare pentru coturn există, iar serverul emite deja credențiale efemere cu nume de utilizator pseudonim. Pe o instanță unde releul nu e configurat, apelurile eșuează în spatele unui NAT prin care STUN singur nu poate trece.
- Parțial Escrow Logica e scrisă și acoperită de teste — derivarea cheilor, regulile de decizie, verificarea contului doi-din-trei, amprenta termenilor, dosarul arbitrului: 62 de teste pe Android și 14 pe server. Dar n-a rulat niciodată cu bani adevărați, iar două bucăți lipsesc: semnarea propriu-zisă de către arbitru și cheia lui. Până atunci e o schemă verificată pe hârtie și în teste, nu un serviciu pe care să te bazezi.
- Urmează Instanță publică Instalarea pe server, certificatul TLS și volumul criptat sunt scrise ca proceduri, dar nu rulează încă pentru public. Nu există un loc unde să-ți faci cont astăzi.
- Urmează Codul va fi publicat Intenția e ca sursa să fie deschisă, ca oricine să poată citi ce face aplicația în loc să ne creadă pe cuvânt. La o aplicație care promite că nimeni nu-ți vede mesajele, asta e singura dovadă care contează cu adevărat. Deocamdată depozitul nu are o licență aleasă, deci nu spunem încă sub ce termeni, și nici când.
- Urmează Supraveghere a serverului cu un model de limbaj Plănuim un model care să urmărească semnalele de operare ale serverului și să dea alarma la tipare de atac: rafale de autentificări eșuate, semnături invalide, înregistrări în valuri, dispozitive adăugate sau revocate anormal, conturi lovite de limitarea de rată. Exact evenimentele care ajung deja în jurnalul de audit, unde adresa IP intră trecută prin hash cu o sare regenerată la fiecare pornire. Ce nu va putea face, și de ce: nu va citi mesajele. Nu fiindcă ne abținem, ci fiindcă pe server nu există text în clar — mesajele sunt criptate pe telefon, iar cheile nu ajung niciodată acolo. Un model care rulează pe server vede exact ce vede serverul: plicuri închise, momentul și mărimea lor. Nu e moderare de conținut și nu poate deveni așa ceva fără să spargem criptarea.
Verificat, dar nu pe hardware: legarea cheii de date de amprentă e implementată și raționată, însă nu a fost încă exercitată pe un telefon fizic — emulatorul nu a putut înrola o amprentă. Restul straturilor de stocare sunt acoperite de teste.
Ce poți face acum
Urmărește proiectul
Nu-ți cerem să te înscrii, fiindcă n-ai unde: nu există încă o instanță publică și aplicația nu e în magazine. Ce poți face e să vezi unde a ajuns și să afli când se deschide. Când se va putea instala, o să scrie aici — și o să scrie și ce încă nu merge, ca și acum.
Anunțurile vor apărea pe canalele din subsolul paginii, imediat ce există.