Procedeu de semnătură

Ed25519 explicat matematic

Semnătura atașată fiecărei recenzii McGesund — de la curbă la cheie și până la ecuația pe care browserul cititorului o recalculează singur.

Actualizat: 2026-09-07

1. Despre ce este vorba aici

O recenzie de pe McGesund nu este un câmp de text dintr-o bază de date pe care trebuie să îl crezi pe cuvânt. Ea este semnată digital în momentul trimiterii, iar orice vizitator poate recalcula ulterior această semnătură în propriul browser.

Pentru această semnătură folosim Ed25519. Spre deosebire de FALCON și ML-DSA, care pot fi așezate alături ca ștampile suplimentare, Ed25519 nu este o opțiune: fiecare recenzie semnată o poartă, indiferent de tarif și de modul de depunere.

Un lucru important de la bun început:

Ed25519 nu este o criptare. Textul recenziei trebuie doar să poată fi citit. Semnătura nu dovedește confidențialitatea, ci originea și integritatea.


2. Ce anume se semnează

Nu se semnează textul propriu-zis, ci un obiect de date compact, care fixează fără echivoc textul și tot restul:

{
  "v":   1,
  "typ": "rev-comment",
  "f":   "<ID companie>",
  "c":   "<ID recenzie>",
  "h":   "<SHA-256 al textului recenziei>",
  "rh":  "<SHA-256 al întregului set de date trimis>",
  "rv":  1,
  "qh":  "<SHA-256 al envelope-ului QR, doar la recenziile prin QR>",
  "kid": "<ID cheie>",
  "iat": 1757203200
}

Acest obiect este codificat în CBOR. Această secvență de octeți — nu reprezentarea ei elegantă de mai sus — este mesajul nostru mm. Semnătura și mesajul călătoresc împreună într-un plic:

Envelope=MCG1:    base64url(CBOR[3,  m,  σ])\text{Envelope} = \texttt{MCG1:} \;\|\; \mathrm{base64url}\bigl(\mathrm{CBOR}[\,3,\; m,\; \sigma\,]\bigr)

Cifra 33 este versiunea formatului. Mai mult nu conține — în special nicio semnătură post-cuantică: aceasta se află, dacă există, alături de setul de date, nu în plic.


3. Ce trebuie să realizeze semnătura

Un cititor care ajunge pe profilul unei companii are două întrebări:

  1. Provine această recenzie cu adevărat din sistemul McGesund?
  2. A fost ea modificată ulterior?

Pentru asta există o pereche de chei:

  • o cheie privată — rămâne în serviciul de semnare
  • o cheie publică — o poate avea oricine, este adresată prin ID-ul de cheie (kid) din payload

Semnarea se face cu cheia privată. Verificarea, cu cea publică — și anume în browserul cititorului, nu pe serverul nostru. Aici este esența: o verificare pe care am efectua-o noi înșine și al cărei rezultat l-am comunica nu ar fi o verificare, ci o afirmație.


4. De ce o curbă eliptică?

Orice semnătură are nevoie de un calcul ușor într-un sens și practic imposibil în celălalt. La Ed25519, acesta este înmulțirea scalară pe o curbă eliptică:

a    A=aB.a \;\longmapsto\; A = a\cdot B.

Calcularea punctului public AA pornind de la numărul secret aa costă microsecunde. Deducerea lui aa din AA este problema logaritmului discret — pentru ea nu se cunoaște niciun procedeu care, la această dimensiune, să se încheie în intervale de timp omenești.

Câștigul practic față de procedee mai vechi, precum RSA, este dimensiunea:

cheie publicăsemnătură
RSA-3072384 B384 B
Ed2551932 B64 B

La un nivel de securitate comparabil. 64 de octeți per recenzie nu reprezintă, nici la milioane de recenzii, o dimensiune la care să merite să te gândești.


5. Curba edwards25519

Calculele se fac modulo un număr prim:

p=225519.p = 2^{255}-19.

De aici și numele. Curba este o curbă Edwards răsucită:

x2+y2  =  1+dx2y2,d=121665121666modp.-x^2+y^2 \;=\; 1 + d\,x^2y^2, \qquad d = -\frac{121665}{121666} \bmod p.

Un „punct” este o pereche de numere (x,y)(x,y) din {0,,p1}\{0,\dots,p-1\} care satisface această ecuație. Nu există nicio curbă de văzut — desenul din secțiunea următoare este un ajutor intuitiv peste numerele reale, nu o imagine a spațiului de calcul real.

Mai apar două mărimi:

  • un punct de bază BB, stabilit prin convenție,
  • ordinul \ell al subgrupului generat de BB:
=2252+27742317777372353535851937790883648493.\ell = 2^{252} + 27742317777372353535851937790883648493.

\ell este prim. Asta înseamnă: dacă aduni BB la sine însuși mereu și mereu, parcurgi exact \ell puncte diferite și ajungi apoi din nou la început. De aceea toate calculele cu scalari se fac modulo \ell, iar toate calculele cu coordonate modulo pp. Confundarea acestor două numere este greșeala clasică de începător.


6. Adunarea punctelor

Două puncte sunt combinate într-un al treilea după o formulă fixă:

x3=x1y2+y1x21+dx1x2y1y2,y3=y1y2x1x21dx1x2y1y2.x_3=\frac{x_1y_2+y_1x_2}{1+d\,x_1x_2y_1y_2}, \qquad y_3=\frac{y_1y_2-x_1x_2}{1-d\,x_1x_2y_1y_2}.

Elementul neutru este (0,1)(0,1) — punctul din care începe calculul.

Această formulă are o proprietate care nu se vede și care este mai importantă pentru securitate decât orice constantă: ea este completă. Funcționează pentru toate intrările, fără cazuri speciale pentru „ambele puncte sunt egale” sau „rezultatul este elementul neutru”. La curbele Weierstrass mai vechi aceste cazuri speciale există, iar fiecare dintre ele este o ramificație în program — o ramificație al cărei timp de execuție se poate măsura. Cine măsoară cât durează o semnătură află, la asemenea procedee, ceva despre cheia secretă.

Formule complete înseamnă: mereu aceeași cale de calcul, mereu același timp, nimic de măsurat.


7. Înmulțirea scalară — strada cu sens unic

nBn\cdot B înseamnă: adună BB la sine însuși exact de nn ori. La un nn de 253 de biți, asta ar însemna o muncă absurd de mare — de aceea se dublează:

B2B4B8BB \to 2B \to 4B \to 8B \to \dots

iar din aceste rezultate intermediare se compune nn-ul dorit. În jur de 253 de dublări sunt suficiente pentru orice nn. Aceasta este calea înainte.

Înapoi, această scurtătură nu există. A determina numărul aa pornind de la punctul AA înseamnă a rezolva problema logaritmului discret.

(0,1) — element neutruB2B3B4B5B6B
O curbă Edwards cu primii multipli ai punctului de bază, calculați cu legea de adunare reală. Peste numerele reale ei se deplasează încă vizibil ordonat de-a lungul curbei — drumul ar putea fi refăcut înapoi. Modulo p dispare exact această ordine, iar pe asta se sprijină securitatea.

În procedeul real se calculează modulo pp. Acolo nu există niciun „stânga”, niciun „dreapta” și nicio apropiere: din 17B17\,B și 18B18\,B rezultă două perechi de numere fără nicio înrudire vizibilă.


8. Perechea de chei a serviciului de semnare

La început stau 32 de octeți aleatori, seed-ul. Tot restul se derivă din el:

h=SHA-512(Seed),h=h0..31  a    h32..63prefix.h = \mathrm{SHA\text{-}512}(\text{Seed}), \qquad h = \underbrace{h_{0..31}}_{\to\;a}\;\|\;\underbrace{h_{32..63}}_{\text{prefix}}.

Din prima jumătate ia naștere scalarul secret aa, însă nu nemodificat. Trei biți sunt setați, respectiv șterși — așa-numitul clamping:

  • cei mai de jos trei biți sunt puși pe zero: astfel aa devine un multiplu de 8. Motivul este cofactorul 8 al curbei — grupul complet de puncte este de opt ori mai mare decât subgrupul de ordin \ell. Un aa divizibil cu 8 ajunge garantat în subgrupul corect și nu dezvăluie nimic despre punctele de ordin mic.
  • bitul cel mai de sus este șters, iar cel imediat următor este setat: astfel aa are întotdeauna aceeași lungime în biți. Un aa mai scurt ar necesita mai puține dublări — și, din nou, s-ar putea citi ceva din timpul de execuție.

Cheia publică este apoi pur și simplu

A=aB,A = a\cdot B,

stocată pe 32 de octeți: coordonata yy și, în bitul cel mai semnificativ, semnul lui xx. Pe xx îl recalculează verificatorul singur din ecuația curbei — cele două soluții diferă doar prin semn, iar care dintre ele este cea corectă o spune acest singur bit.

A doua jumătate a valorii hash, prefixul, nu este necesară pentru cheie. Ea intră în joc în secțiunea următoare.


9. De ce aleatoriul de aici nu este aleatoriu

Orice semnătură de acest tip are nevoie de o valoare unică rr, numită adesea nonce. Ea nu are voie să se repete niciodată: cine deține două semnături cu același rr poate deduce cheia secretă cu algebră de școală.

Exact de asta au eșuat sisteme reale. Cazul cel mai cunoscut este verificarea semnăturilor unei console de jocuri, al cărei producător a folosit în 2010 mereu același nonce — cheia privată devenea astfel public reconstruibilă.

Ed25519 rezolvă asta prin faptul că nu folosește deloc aleatoriu:

r=SHA-512(prefix    m)mod.r = \mathrm{SHA\text{-}512}(\text{prefix}\;\|\;m) \bmod \ell.

Nonce-ul depinde de prefixul secret și de mesaj. De aici rezultă două lucruri:

  • Două recenzii diferite produc, cu o probabilitate covârșitoare, valori rr diferite — cazul repetării nu apare.
  • Aceeași recenzie produce întotdeauna aceeași semnătură. Un proces de semnare poate fi astfel reprodus, iar un generator de numere aleatoare slab de pe server nu poate strica nimic, pentru că nu este nevoie de niciunul.

Pentru un portal de recenzii cu multe semnături pe zi, acesta nu este un avantaj academic. Este diferența dintre „o eroare în sursa de aleatoriu ar fi fatală” și „nu există nicio sursă de aleatoriu care să poată ceda”.


10. Semnarea

Trei rânduri, nimic mai mult:

r=H(prefix    m)mod,R=rB,r = H(\text{prefix}\;\|\;m) \bmod \ell, \qquad R = r\cdot B,
k=H(R    A    m)mod,k = H(R \;\|\; A \;\|\; m) \bmod \ell,
S=(r+ka)mod.S = (r + k\,a) \bmod \ell.

Semnătura este perechea

σ=(R,S),\sigma = (R,\,S),

32 de octeți pentru punctul RR, 32 de octeți pentru numărul SS — în total 64 de octeți.

Demn de remarcat este al doilea rând: în kk intră RR, cheia publică AA și mesajul. Faptul că AA este inclusă în hash nu este un accesoriu — împiedică atacurile prin care o semnătură este reinterpretată pentru o altă cheie.


11. Verificarea

Browserul cititorului cunoaște: recenzia mm, semnătura (R,S)(R,S) și cheia publică AA. El recalculează kk și verifică o singură ecuație:

SB  =  R+kA\boxed{S\cdot B \;=\; R + k\cdot A}

Dacă ea se verifică, semnătura este validă. RFC 8032 permite suplimentar varianta înmulțită cu cofactorul, 8SB=8R+8kA8S\cdot B = 8R + 8k\cdot A, care tratează mai îngăduitor câteva cazuri marginale.

Niciun server nu este întrebat, niciun serviciu nu trebuie să fie disponibil. Cheia publică este suficientă.


12. De ce ecuația se verifică

Este suficient să înlocuim:

SB=(r+ka)B=rB+k(aB)=R+kA.S\cdot B = (r + k\,a)\cdot B = r\cdot B + k\,(a\cdot B) = R + k\cdot A.

Tot secretul stă în transformarea din mijloc: înmulțirea scalară este compatibilă cu adunarea. Cine cunoaște aa poate calcula un SS care satisface ecuația. Cine nu cunoaște aa ar trebui să găsească, pentru un kk ales de el, un SS potrivit — iar asta înseamnă să rezolve logaritmul discret.


13. Un mini-exemplu calculat integral

Cu numerele reale nu se poate verifica nimic — valorile de 253 de biți nu pot fi controlate în minte. De aceea, același procedeu într-un grup minuscul, în care fiecare pas poate fi urmărit cu calculatorul de buzunar.

Pasul 1: Grupul

Calculăm cu resturile modulo 2323 și luăm g=2g = 2. Avem

211=2048=8923+11(mod23),2^{11} = 2048 = 89\cdot 23 + 1 \equiv 1 \pmod{23},

așadar gg generează un subgrup de ordin =11\ell = 11. Puterile sunt:

nn1234567891011
gng^n248169181336121

gg preia rolul punctului de bază BB, iar înmulțirea pe cel al adunării punctelor. Scalarii se calculează modulo 1111, valorile modulo 2323.

Pasul 2: Perechea de chei

Fie secretul a=6a = 6. Atunci

A=ga=26=6418(mod23).A = g^a = 2^6 = 64 \equiv 18 \pmod{23}.

A=18A = 18 poate fi cunoscut de oricine.

Pasul 3: Nonce și commitment

Din prefix și recenzie să rezulte r=4r = 4. De aici:

R=gr=24=16.R = g^r = 2^4 = 16.

Pasul 4: Challenge-ul

Hash-ul peste RR, AA și recenzie să dea

k=5.k = 5.

Pasul 5: Semnătura

S=(r+ka)mod11=(4+56)mod11=34mod11=1.S = (r + k\,a) \bmod 11 = (4 + 5\cdot 6) \bmod 11 = 34 \bmod 11 = 1.

Semnătura este perechea (R,S)=(16,1)(R,S) = (16,\,1).

Pasul 6: Browserul verifică

El calculează ambele părți. În stânga:

gS=21=2.g^S = 2^1 = 2.

În dreapta, cu 1853(mod23)18^5 \equiv 3 \pmod{23}:

RAk=163=482(mod23).R\cdot A^{k} = 16\cdot 3 = 48 \equiv 2 \pmod{23}.

Ambele părți dau 22:

Semna˘tura˘ valida˘\boxed{\text{Semnătură validă}}

Pasul 7: Cineva modifică textul recenziei

Textul intră în hash, așadar se schimbă challenge-ul — să zicem la k=7k' = 7. Semnătura rămâne neschimbată la (16,1)(16,1), dar partea dreaptă nu. Cu 1876(mod23)18^7 \equiv 6 \pmod{23}:

RAk=166=964(mod23)    2=gSR\cdot A^{k'} = 16\cdot 6 = 96 \equiv 4 \pmod{23} \;\neq\; 2 = g^S
Semna˘tura˘ invalida˘\boxed{\text{Semnătură invalidă}}

Putem șterge o recenzie. Nu o putem modifica fără ca acest lucru să iasă la iveală.

Notă de onestitate privind exemplul

Aici s-a calculat în grupul multiplicativ modulo 2323, nu pe o curbă: gSg^S ține locul lui SBS\cdot B, iar produsul RAkR\cdot A^k pe cel al adunării de puncte R+kAR + k\cdot A. Structura este aceeași, și exact despre asta este vorba. Diferite sunt ordinele de mărime: =11\ell = 11 față de 2252\ell \approx 2^{252}, iar acolo cheia nu se găsește încercând cele unsprezece posibilități.


14. Ce se întâmplă dacă cineva modifică recenzia

Să presupunem că cineva cu acces la baza de date — inclusiv cineva de la noi — modifică textul recenziei sau una dintre inimi. Atunci se schimbă setul de date și, odată cu el, cel puțin una dintre cele două valori hash h și rh din payload. Astfel se schimbă mm, deci challenge-ul kk, deci partea dreaptă a ecuației de verificare. Semnătura veche nu se mai potrivește.

Fraza decisivă în această privință: putem șterge o recenzie, dar nu o putem modifica pe nesimțite. La McGesund, aceeași verificare rulează suplimentar în fiecare noapte, pe server, asupra întregului fond — o recenzie care nu o trece nu mai intră în media companiei.


15. De ce eșuează un atacator

El cunoaște cheia publică AA, punctul de bază BB, curba și fiecare semnătură emisă până acum. Ceea ce îi lipsește este aa.

Cel mai bun atac clasic cunoscut asupra problemei logaritmului discret într-un grup de ordin \ell are nevoie de aproximativ \sqrt{\ell} pași. La 2252\ell \approx 2^{252} acestea sunt în jur de

21262^{126}

operații. Pentru comparație: chiar și o mașină care ar face un miliard de miliarde (101810^{18}) de pași pe secundă ar avea nevoie pentru asta de un multiplu al vârstei universului.

A falsifica fără cheie ar însemna să găsești, pentru un kk ales de tine, un SS potrivit — aceeași sarcină, în altă deghizare.


16. De ce Ed25519 și nu ECDSA

Ambele se bazează pe aceeași problemă. Diferența stă în tot ce se întâmplă în jur:

ECDSA (curbe NIST)Ed25519
Noncenecesită aleatoriu proaspătdeterminist, din prefix și mesaj
Formulecazuri speciale, ramificații dependente de datecomplete, o singură cale de calcul
Parametrii curbeioriginea constantelor nu a fost niciodată explicată completaleși după criterii verificabile
Dimensiunea semnăturii64–72 B, codare variabilăfix 64 B
În browserdisponibil de mult timpnativ din 2023/2024, altfel ca bibliotecă JS

Pentru noi, nonce-ul a fost argumentul decisiv. Un portal de recenzii semnează des și automatizat; un procedeu la care o singură valoare aleatoare slabă dezvăluie cheia este alegerea greșită pentru așa ceva.


17. Ce nu realizează Ed25519

Ed25519 se bazează pe logaritmul discret — și exact această problemă o rezolvă eficient un calculator cuantic suficient de mare, cu algoritmul lui Shor. Dacă și când vor exista asemenea mașini rămâne deschis. Pentru o recenzie care trebuie să fie verificabilă și peste zece ani, aceasta este totuși o întrebare la care trebuie răspuns astăzi.

De aceea, alături de semnătura Ed25519 poate apărea o ștampilă rezistentă la calculul cuantic:

Niciuna dintre ele nu înlocuiește Ed25519, ci se așază alături. Dacă unul dintre procedee cade, celălalt continuă să susțină.


18. Fluxul în imagine

SERVICIUL DE SEMNARE (MCGESUND)BROWSERUL VIZITATORULUIscalar privat a + prefix (din seed)Payload m = {companie, recenzie, h, rh, iat}r = H(prefix ‖ m) mod ℓR = r · Bk = H(R ‖ A ‖ m) mod ℓS = (r + k · a) mod ℓSemnătura σ = (R, S) + kidRecenzie + σ + cheia publică Arecalcularea lui k din R, A și mS · B = R + k · A ?validăinvalidă
De la payload până la bifa din browser. Deasupra liniei de separare, totul se întâmplă o singură dată, la trimitere; dedesubt, din nou la fiecare cititor — pe dispozitivul său, doar cu cheia publică.

19. Ce face McGesund concret cu asta

Envelope-ul. Fiecare recenzie semnată poartă un plic MCG1: cu versiunea formatului, payload-ul și semnătura Ed25519. Câmpul kid din payload spune despre ce cheie este vorba; cheia publică asociată este livrată de server la cerere — ea este publică, nu are nimic de protejat.

Verificarea în browser. Chrome și Firefox pot folosi Ed25519 nativ, prin interfața WebCrypto, din 2023/2024. Safari nu — acolo apelul aruncă o eroare în loc să verifice. De aceea codul nostru de verificare revine la o implementare pur JavaScript, care este încărcată doar acolo unde este nevoie de ea. Astfel, verificarea semnăturii se realizează în orice browser, și anume pe dispozitivul cititorului.

Ancora temporală. Amprenta cheii de semnare este ancorată printr-un bloc Bitcoin, prin OpenTimestamps. Astfel se poate dovedi nu doar că semnătura este autentică, ci și că cheia exista deja la un anumit moment — fără ca cineva să fie nevoit să creadă marcajul nostru de timp.

Legarea de conținut. Payload-ul poartă rh, hash-ul peste întregul set de date trimis: text, inimi, statusul geo, datele privind ocazia și proveniența. Astfel, semnătura Ed25519 leagă nu doar textul, ci tot ce se afișează alături de recenzie.


20. O frază de reținut

Ed25519 transforma˘ un numa˘r secret ıˆntr-o ecuațiepe care oricine o verifica˘ și nimeni nu o poate inventa.\boxed{ \begin{array}{c} \text{Ed25519 transformă un număr secret într-o ecuație}\\ \text{pe care oricine o verifică și nimeni nu o poate inventa.} \end{array}}

Cine deține scalarul secret semnează în microsecunde. Cine nu îl deține ar trebui să rezolve un logaritm discret într-un grup cu aproximativ 22522^{252} elemente.

Pentru cititorul unei recenzii asta înseamnă pur și simplu: nu trebuie să ne creadă. Poate să verifice singur.