Securitate · În detaliu

Ciclul de viață criptografic complet

O trecere precisă prin ce se întâmplă cu datele tale la fiecare pas — cu primitivele, parametrii și granițele de încredere explicate. Fiecare pas începe cu un rezumat pe înțelesul tuturor, ca să poți citi la nivelul de detaliu pe care îl vrei.

Pasul 01 · Criptare

Secretul tău e sigilat pe dispozitivul tău

Pe scurt: amestecarea are loc în browserul tău, înainte ca ceva să fie încărcat. Ce primim noi e deja ilizibil.

Când apeși Criptează, browserul generează o cheie de conținut nouă, de 256 de biți, din WebCrypto CSPRNG și îți criptează datele cu AES-256-GCM. GCM este autentificat: fiecare bucată are o etichetă de 128 de biți, așa că orice modificare ulterioară este detectată, în loc să fie decriptată pe tăcute.

Textul și fișierele sunt tratate identic — ambele devin un singur blob binar opac, completat până la o mărime standard, astfel încât o parolă scurtă și un fișier mic arată la fel. Textul în clar nu atinge niciodată rețeaua și nu părăsește niciodată memoria filei.

CifruAES-256-GCM, bucăți de 64 KiB
Cheie de conținut256 de biți, nouă pentru fiecare secret
Nonceprefix aleatoriu de 7 octeți + contor
Etichetă de autentificare128 de biți pe bucată
CompletarePadmé, minimum 64 KiB

Pasul 02 · Păstrarea cheii

Cheia stă ascunsă în link, nu pe serverele noastre

Pe scurt: partea linkului de după # conține cheia — iar browserele nu trimit niciodată acea parte vreunui server.

Linkul tău conține un seed aleatoriu de 256 de biți în fragmentul URL — tot ce urmează după #. Conform specificației URL, browserul elimină fragmentul și nu îl include niciodată în cererea trimisă serverelor noastre. Din acest seed, browserul derivă cu HKDF o valoare de căutare, prin care găsește secretul, și cheia care despachetează cheia de conținut. Serverul vede doar un hash al valorii de căutare.

Browserul destinatarului citește seedul din fragment și face aceeași derivare local. Asta înseamnă aici „zero-knowledge”: simpla deținere a textului cifrat nu folosește la nimic fără link.

Locul cheiifragment URL #
Trimisă serverului?niciodată
Seed32 de octeți aleatorii, base64url
DerivareHKDF-SHA-256
Serverul stocheazădoar SHA-256(lookup)

Pasul 03 · Frază de acces opțională

Un al doilea lacăt, pe care îl dețin doar oamenii

Pe scurt: adaugă o frază de acces și nici măcar cineva care are linkul complet nu poate deschide secretul fără ea.

Dacă setezi o frază de acces, aceasta este întărită cu Argon2id — o funcție de derivare a cheii memory-hard — și combinată cu seedul în cheia care împachetează cheia de conținut. Fraza de acces în sine nu este niciodată transmisă sau stocată; o știți doar tu și destinatarul. Încercările greșite sunt reluate în browserul destinatarului, pe date pe care acesta le are deja, așa că serverul nu le poate număra.

Caracterul memory-hard face ca ghicirea offline la scară mare să fie costisitoare chiar și pe GPU-uri și ASIC-uri. Trimite fraza de acces pe un alt canal decât linkul, iar cei doi factori nu se întâlnesc niciodată în același loc. Modulul Argon2 este descărcat la fiecare creare și afișare, așa că rețeaua nu poate ști care secrete folosesc o frază de acces.

KDFArgon2id
Saltaleatoriu, 128 de biți
ÎmpachetareAES-256-GCM, IV de 96 de biți

Pasul 04 · Tranzit și stocare

De pe dispozitivul tău pleacă doar text cifrat

Pe scurt: stocăm o cutie încuiată și un moment de expirare. Nimic altceva — niciun text în clar, nicio cheie, nicio evidență despre tine.

Blobul este încărcat prin TLS și stocat în repaus ca text cifrat, alături de credențiale hash-uite, durata lui de viață și un moment de expirare rotunjit. În mod deliberat nu păstrăm identitatea expeditorului, destinatarul, jurnale de IP, momentul creării sau istoricul accesărilor. Nu există un sistem de conturi care să lege un secret de o persoană. Limitarea ratei funcționează pe un HMAC al adresei, cu un salt care se rotește, așa că nimic de dinaintea unei rotații nu poate fi legat de ceva de după ea.

Pentru că obiectul stocat nu are niciun sens fără seedul din fragment, o compromitere a serverului sau o citație judiciară scoate la iveală doar octeți opaci și hash-uri din care nu se poate obține nimic.

În tranzitTLS
În repaustext cifrat + chei hash-uite + expirare
Jurnaleniciunul per secret

Pasul 05 · Preluare și distrugere

Prima citire câștigă — apoi totul e șters

Pe scurt: deschiderea unui link de unică folosință predă cutia o singură dată și șterge copia de pe server. Sau o distrugi tu, oricând.

Nu se descarcă nimic la încărcarea paginii de afișare: cererea pleacă doar la un clic sau o apăsare de tastă reală, așa că scannerele de linkuri și previzualizările din chat nu pot consuma un secret. Pentru un secret de unică folosință, serverul revendică rândul printr-o singură actualizare condiționată — exact o cerere câștigă — iar secretul este considerat consumat din acel moment. Același browser poate descărca din nou timp de 15 minute dacă se întrerupe conexiunea; nimeni altcineva nu poate, iar o revendicare neconfirmată este distrusă, niciodată anulată. Secretele cu termen sunt o simplă citire până expiră.

Fiecare secret are și un link de distrugere privat. Deschiderea lui nu distruge nimic în sine; confirmarea șterge imediat textul cifrat — înainte ca vreun destinatar să-l poată citi.

Unică folosințărevendicare atomică, apoi distrugere
Interval de redescărcare15 min, doar același client
Expirare15 min – 14 zile
Controlul proprietaruluilink de distrugere

Modelul de amenințări

Ce poate și ce nu poate vedea shhnote

Versiunea sinceră. Iată exact unde se află granița de încredere.

Nu părăsește niciodată dispozitivul tău

Ce nu putem vedea

Textul tău în clar · cheia de conținut și seedul · fraza ta de acces · dacă a fost setată o frază de acces · cine a creat sau a deschis un secret · când a fost creat · jurnale de acces la nivel de IP. Nimic din toate acestea nu este transmis sau păstrat.

Stocat pe serverele noastre

Ce deținem

Un blob criptat pe care nu îl putem deschide · categoria lui de mărime după completare · hash-uri unidirecționale ale valorilor pe care browserul tău le folosește ca să-l găsească sau să-l distrugă · dacă este de unică folosință sau cu termen · un moment de expirare rotunjit. Toate inutile fără seedul din linkul tău.

Bine de știut

Limitele, spuse cinstit

Oricine are linkul complet (și fraza de acces, dacă a fost setată) poate citi un secret de unică folosință — tratează linkul ca pe secretul însuși. După ce un secret este afișat, pagina suprascrie ce poate când pleci de pe ea, dar JavaScript nu poate garanta asta; închide fila când ai terminat. Un browser controlat automat, care injectează intrări reale, poate deschide un secret de unică folosință la fel cum ar face-o un om — destinatarul nu mai găsește apoi nimic, ceea ce este rezultatul onest. Ștergerea unui secret elimină înregistrarea; resturi criptate pot persista în jurnale, în spațiul liber de pe disc sau în backupuri până la suprascriere, ca text cifrat fără cheie. Secretele mari stocate în afara bazei de date poartă momentul în care a fost scris fișierul. Și, ca la orice aplicație web, ai încredere în codul servit browserului tău — de aceea shhnote este open source și poate fi găzduit de oricine.

Specificația criptografică

Toate primitivele, într-un singur loc

Criptare

AES-256-GCM

Criptare simetrică autentificată, în bucăți de 64 KiB. O cheie de 256 de biți plus o etichetă de integritate pentru fiecare bucată, așa că orice modificare sau trunchiere este detectată — nu doar lăsată ilizibilă.

Derivarea cheii

HKDF · Argon2id

Cheile și identificatorii provin din seed prin HKDF-SHA-256. Frazele de acces opționale sunt întărite cu un KDF memory-hard, care face forța brută offline lentă și costisitoare chiar și pe hardware dedicat.

Aleatoriu

WebCrypto CSPRNG

Seedurile, cheile, salturile și nonce-urile provin din generatorul criptografic sigur al browserului. Niciodată Math.random(), niciodată previzibile.

Păstrarea cheii

Fragment URL #

Seedul stă după # în linkul tău. Browserele nu transmit niciodată fragmentul, așa că acesta nu ajunge niciodată pe serverele noastre.

În tranzit

TLS

De pe dispozitivul tău pleacă doar text cifrat, transportat prin TLS modern. Ce primim noi e un blob opac pe care nu îl putem deschide.

În repaus

Text cifrat + hash-uri

Păstrăm un blob criptat, hash-uri unidirecționale ale credențialelor lui și un moment de expirare rotunjit — fără text în clar, fără chei, fără metadate despre expeditor sau destinatar.

Întrebări tehnice

Pentru cei atenți la securitate

Cum este garantată vizualizarea unică în cazul cererilor simultane?

Afișarea execută o singură actualizare condiționată, care mută rândul din „activ” în „revendicat”. Două cereri simultane nu pot reuși amândouă; a doua găsește o înregistrare deja revendicată și primește același răspuns „niciun secret găsit” ca oricine altcineva. Revendicarea nu este anulată niciodată: dacă descărcarea se pierde, deținătorul tokenului de revendicare descarcă din nou în intervalul permis, altfel secretul este distrus necitit.

De ce fragmentul URL și nu un parametru de interogare?

Parametrii de interogare sunt trimiși serverului și ajung în jurnalele de acces, în proxy-uri și în instrumentele de analiză. Fragmentul (de după #) este definit de specificația URL ca să rămână pe partea clientului — browserul nu îl pune niciodată în cererea HTTP. Această proprietate este întreaga bază a designului zero-knowledge. După afișare, pagina elimină și fragmentul din bara de adrese și din istoric.

Ce împiedică scannerele de linkuri să consume prematur secretele de unică folosință?

Pagina de vizualizare este același document static pentru toate secretele și nu descarcă nimic la încărcare. Cererea este trimisă doar la un clic sau o apăsare de tastă reală — un click() prin script sau o trimitere de formular nu contează. Scannerele automate (securitate e-mail, previzualizări din chat, antivirus) încarcă doar acel cadru static.

Pot verifica sau găzdui singur serviciul?

Da. Tot codul sursă este public sub licența AGPLv3, protocolul este descris într-o specificație cu vectori de conformitate față de care orice implementare se poate verifica, și există un ghid de găzduire proprie. Poți audita criptografia din client și îți poți rula propria instanță, astfel încât granița de încredere să fie în întregime a ta.

Se înregistrează ceva pentru prevenirea abuzurilor?

Nu păstrăm jurnale de acces per secret și nici istoric de IP-uri. Limitarea ratei folosește un hash cu cheie al adresei, cu un salt care se rotește și care șterge odată cu el toate contoarele. Raportările de abuz sunt numărate pe zi; nu există nicio evidență a secretului raportat.

Sfaturi pentru o partajare sigură

  • Trimite fraza de acces pe altă cale decât linkul, de exemplu linkul prin e-mail și fraza de acces la telefon.
  • Alege cea mai scurtă perioadă de expirare care ți se potrivește.
  • Folosește un secret de unică folosință pentru parole și alte informații care ar trebui citite o singură dată.

Raportarea unei vulnerabilități

Dacă crezi că ai găsit o problemă de securitate pe acest site, te rugăm să ne scrii la [email protected] și să ne spui în privat, înainte de a spune altcuiva. Include ce ai găsit și cum se poate reproduce.

Ne angajăm să:

  • răspundem în 5 zile lucrătoare;
  • te ținem la curent cât timp remediem problema;
  • îți recunoaștem contribuția când publicăm remedierea, dacă dorești.

Te rugăm ca, în timpul testării, să nu accesezi datele altor persoane, să nu perturbi serviciul și să nu rulezi scanări automate care îl încarcă puternic.

Pentru vulnerabilități în software-ul shhnote propriu-zis, vezi politica de securitate a proiectului.

Creează un secret Vezi sursa pe GitHub

Încearcă — durează zece secunde

Scrie ceva secret, primește linkul de unică folosință și vezi-l cum dispare.

Creează un secret