Schematy podpisu

Ed25519 wyjaśniony matematycznie

Podpis, który towarzyszy każdej opinii w McGesund — od krzywej przez klucz aż po równanie, które przelicza przeglądarka czytelnika.

Stan: 2026-09-07

1. O co tutaj chodzi

Opinia w McGesund nie jest polem tekstowym w bazie danych, któremu trzeba wierzyć. Przy wysłaniu zostaje podpisana cyfrowo, a każdy odwiedzający może później przeliczyć ten podpis w swojej własnej przeglądarce.

Do tego podpisu używamy Ed25519. W przeciwieństwie do FALCON i ML-DSA, które można dodatkowo dołożyć obok jako stemple, Ed25519 nie jest opcją: każda podpisana opinia go niesie, niezależnie od taryfy i drogi przesłania.

Ważna uwaga na wstępie:

Ed25519 nie jest szyfrowaniem. Tekst opinii ma przecież być czytany. Podpis nie dowodzi poufności, lecz pochodzenia i nienaruszalności.


2. Co dokładnie jest podpisywane

Podpisywany jest nie tekst ciągły, lecz kompaktowy obiekt danych, który jednoznacznie przybija tekst i całą resztę:

{
  "v":   1,
  "typ": "rev-comment",
  "f":   "<ID firmy>",
  "c":   "<ID opinii>",
  "h":   "<SHA-256 tekstu opinii>",
  "rh":  "<SHA-256 całego rekordu przesłanej opinii>",
  "rv":  1,
  "qh":  "<SHA-256 koperty QR, tylko przy opiniach z QR>",
  "kid": "<ID klucza>",
  "iat": 1757203200
}

Ten obiekt zostaje zakodowany do CBOR. Ta sekwencja bajtów — a nie jej ładna postać powyżej — jest naszą wiadomością mm. Podpis i wiadomość wędrują razem do koperty:

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

33 to wersja formatu. Nic więcej w niej nie ma — w szczególności żadnego podpisu postkwantowego: ten leży, jeśli istnieje, obok rekordu danych, a nie w kopercie.


3. Co ma zapewniać podpis

Czytelnik, który trafia na profil firmy, staje przed dwoma pytaniami:

  1. Czy ta opinia rzeczywiście pochodzi z systemu McGesund?
  2. Czy została później zmieniona?

Służy do tego para kluczy:

  • klucz prywatny — pozostaje w usłudze podpisującej
  • klucz publiczny — może go mieć każdy, adresowany przez identyfikator klucza (kid) w payloadzie

Podpisuje się kluczem prywatnym. Weryfikuje się publicznym — i to w przeglądarce czytelnika, a nie na naszym serwerze. I o to właśnie chodzi: weryfikacja, którą przeprowadzalibyśmy sami i której wynik jedynie komunikowalibyśmy, nie byłaby weryfikacją, lecz twierdzeniem.


4. Dlaczego krzywa eliptyczna?

Każdy podpis potrzebuje działania, które w jedną stronę jest łatwe, a w drugą praktycznie niemożliwe. W Ed25519 jest to mnożenie przez skalar na krzywej eliptycznej:

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

Obliczenie punktu publicznego AA z tajnej liczby aa kosztuje mikrosekundy. Wnioskowanie z AA z powrotem o aa to problem logarytmu dyskretnego — nie jest znana metoda, która przy tym rozmiarze uporałaby się z nim w ludzkich ramach czasowych.

Praktyczna korzyść w porównaniu ze starszymi metodami, takimi jak RSA, to rozmiar:

klucz publicznypodpis
RSA-3072384 B384 B
Ed2551932 B64 B

Przy porównywalnym poziomie bezpieczeństwa. 64 bajty na opinię to nawet przy milionach opinii nie jest rozmiar, nad którym trzeba się zastanawiać.


5. Krzywa edwards25519

Obliczenia prowadzone są modulo pewna liczba pierwsza:

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

Stąd nazwa. Krzywa jest skręconą krzywą Edwardsa:

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

„Punkt" to para liczb (x,y)(x,y) ze zbioru {0,,p1}\{0,\dots,p-1\}, która spełnia to równanie. Nie ma tu żadnej krzywej do oglądania — rysunek w następnym rozdziale jest pomocą poglądową nad liczbami rzeczywistymi, a nie obrazem rzeczywistej przestrzeni obliczeń.

Dochodzą jeszcze dwie wielkości:

  • ustalony na stałe punkt bazowy BB,
  • rząd \ell podgrupy generowanej przez BB:
=2252+27742317777372353535851937790883648493.\ell = 2^{252} + 27742317777372353535851937790883648493.

\ell jest liczbą pierwszą. Oznacza to: dodając BB wciąż na nowo do siebie samego, przechodzi się przez dokładnie \ell różnych punktów i wraca na początek. Wszystkie obliczenia na skalarach biegną dlatego modulo \ell, a wszystkie obliczenia na współrzędnych modulo pp. Pomylenie tych dwóch liczb to klasyczny błąd początkującego.


6. Dodawanie punktów

Dwa punkty zostają według stałego wzoru przeliczone na trzeci:

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}.

Elementem neutralnym jest (0,1)(0,1) — punkt, w którym liczenie się zaczyna.

Ten wzór ma własność, której po nim nie widać, a która dla bezpieczeństwa jest ważniejsza niż jakakolwiek stała: jest zupełny. Działa dla wszystkich danych wejściowych, bez przypadków szczególnych w rodzaju „oba punkty są równe" albo „wynikiem jest element neutralny". Przy starszych krzywych Weierstrassa takie przypadki szczególne istnieją, a każdy z nich to gałąź w programie — gałąź, której czas wykonania da się zmierzyć. Kto mierzy, jak długo trwa podpisywanie, dowiaduje się przy takich metodach czegoś o kluczu tajnym.

Zupełne wzory oznaczają: zawsze ta sama droga obliczeń, zawsze ten sam czas, nic do zmierzenia.


7. Mnożenie przez skalar — droga jednokierunkowa

nBn\cdot B oznacza: dodać BB dokładnie nn razy do siebie samego. Przy nn o długości 253 bitów byłoby to bezsensownie dużo pracy — dlatego się podwaja:

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

a z tych wyników pośrednich składa się żądane nn. Około 253 podwojeń wystarcza dla każdego nn. To jest droga w przód.

Wstecz takiego skrótu nie ma. Wyznaczenie liczby aa z punktu AA oznacza rozwiązanie problemu logarytmu dyskretnego.

(0,1) — element neutralnyB2B3B4B5B6B
Krzywa Edwardsa z pierwszymi wielokrotnościami punktu bazowego, obliczonymi zgodnie z prawdziwym prawem dodawania. Nad liczbami rzeczywistymi wędrują one po krzywej w wciąż widocznym porządku — drogę dałoby się prześledzić wstecz. Modulo p znika właśnie ten porządek i na tym opiera się bezpieczeństwo.

W rzeczywistej metodzie liczy się modulo pp. Tam nie ma „lewa", nie ma „prawa" i nie ma bliskości: z 17B17\,B i 18B18\,B powstają dwie pary liczb bez jakiegokolwiek rozpoznawalnego pokrewieństwa.


8. Para kluczy usługi podpisującej

Na początku są 32 losowe bajty, seed. Wszystko dalsze zostaje z nich wyprowadzone:

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

Z pierwszej połowy powstaje tajny skalar aa, jednak nie w niezmienionej postaci. Trzy bity zostają ustawione względnie wyzerowane — tak zwany clamping:

  • trzy najniższe bity zostają wyzerowane: aa staje się przez to wielokrotnością 8. Powodem jest kofaktor 8 krzywej — pełna grupa punktów jest ośmiokrotnie większa niż podgrupa rzędu \ell. Podzielne przez 8 aa trafia z gwarancją do właściwej podgrupy i nie zdradza niczego o punktach małego rzędu.
  • najwyższy bit zostaje wyzerowany, a drugi od góry ustawiony: aa ma dzięki temu zawsze tę samą długość bitową. Krótsze aa wymagałoby mniej podwojeń — i znowu z czasu wykonania dałoby się coś odczytać.

Klucz publiczny to następnie po prostu

A=aB,A = a\cdot B,

zapisany jako 32 bajty: współrzędna yy, a w najstarszym bicie znak xx. Wartość xx weryfikujący wylicza sobie sam z równania krzywej — oba rozwiązania różnią się tylko znakiem, a o które chodzi, mówi ten jeden bit.

Druga połowa wartości skrótu, prefiks, nie jest potrzebna do klucza. Zostanie użyta w następnym rozdziale.


9. Dlaczego losowość nie jest tu losowa

Każdy podpis tej konstrukcji potrzebuje jednorazowej wartości rr, często zwanej nonce. Nigdy nie może się ona powtórzyć: kto ma dwa podpisy z tym samym rr, wyliczy klucz tajny szkolną algebrą.

Właśnie na tym poległy realne systemy. Najbardziej znany przypadek to weryfikacja podpisów pewnej konsoli do gier, której producent w 2010 roku używał zawsze tego samego nonce — klucz prywatny dał się przez to publicznie zrekonstruować.

Ed25519 rozwiązuje to, nie używając losowości w ogóle:

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

Nonce zależy od tajnego prefiksu i od wiadomości. Wynikają z tego dwie rzeczy:

  • Dwie różne opinie dają z przytłaczającym prawdopodobieństwem różne rr — przypadek powtórzenia nie występuje.
  • Ta sama opinia daje zawsze ten sam podpis. Proces podpisywania da się dzięki temu odtworzyć, a zły generator losowy na serwerze nie może niczego zepsuć, bo żaden nie jest potrzebny.

Dla portalu z opiniami, w którym powstaje wiele podpisów dziennie, nie jest to zaleta akademicka. To różnica między „błąd w źródle losowości byłby fatalny" a „nie ma źródła losowości, które mogłoby zawieść".


10. Podpisywanie

Trzy wiersze, nic więcej:

r=H(prefiks    m)mod,R=rB,r = H(\text{prefiks}\;\|\;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.

Podpisem jest para

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

32 bajty na punkt RR, 32 bajty na liczbę SS — razem 64 bajty.

Godny uwagi jest drugi wiersz: w kk wchodzą RR, klucz publiczny AA oraz wiadomość. To, że AA jest współhaszowany, nie jest dodatkiem — zapobiega atakom, w których podpis zostaje przeinterpretowany na inny klucz.


11. Weryfikacja

Przeglądarka czytelnika zna: opinię mm, podpis (R,S)(R,S) i klucz publiczny AA. Wylicza kk na nowo i sprawdza jedno jedyne równanie:

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

Jeśli się zgadza, podpis jest ważny. RFC 8032 dopuszcza dodatkowo wersję pomnożoną przez kofaktor, 8SB=8R+8kA8S\cdot B = 8R + 8k\cdot A, która traktuje niektóre przypadki brzegowe łagodniej.

Żaden serwer nie jest pytany, żadna usługa nie musi być dostępna. Klucz publiczny wystarcza.


12. Dlaczego równanie się zgadza

Wystarczy podstawić:

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.

Cała sztuczka tkwi w środkowym przekształceniu: mnożenie przez skalar jest zgodne z dodawaniem. Kto zna aa, wyliczy SS spełniające to równanie. Kto aa nie zna, musiałby do samodzielnie wybranego kk znaleźć pasujące SS — a to znaczy rozwiązać logarytm dyskretny.


13. W pełni przeliczony miniprzykład

Na prawdziwych liczbach nie da się niczego przeliczyć — wartości 253-bitowych nie sprawdzi się w pamięci. Dlatego ta sama metoda w maleńkiej grupie, w której każdy krok da się odtworzyć kalkulatorem.

Krok 1: Grupa

Liczymy na resztach modulo 2323 i bierzemy g=2g = 2. Zachodzi

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

gg generuje więc podgrupę rzędu =11\ell = 11. Potęgi wynoszą:

nn1234567891011
gng^n248169181336121

gg przejmuje rolę punktu bazowego BB, a mnożenie — rolę dodawania punktów. Skalary liczy się modulo 1111, wartości modulo 2323.

Krok 2: Para kluczy

Niech tajne będzie a=6a = 6. Wtedy

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

A=18A = 18 może znać każdy.

Krok 3: Nonce i commitment

Niech z prefiksu i opinii wyjdzie r=4r = 4. Stąd:

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

Krok 4: Challenge

Niech skrót z RR, AA i opinii da

k=5.k = 5.

Krok 5: Podpis

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.

Podpisem jest para (R,S)=(16,1)(R,S) = (16,\,1).

Krok 6: Przeglądarka weryfikuje

Wylicza obie strony. Po lewej:

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

Po prawej, przy 1853(mod23)18^5 \equiv 3 \pmod{23}:

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

Obie strony dają 22:

Podpis waz˙ny\boxed{\text{Podpis ważny}}

Krok 7: Ktoś zmienia tekst opinii

Tekst wchodzi do skrótu, zmienia się więc challenge — powiedzmy na k=7k' = 7. Podpis pozostaje niezmieniony przy (16,1)(16,1), ale prawa strona już nie. Przy 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
Podpis niewaz˙ny\boxed{\text{Podpis nieważny}}

Opinię możemy usunąć. Zmienić jej nie możemy tak, żeby nikt tego nie zauważył.

Uwaga o rzetelności przykładu

Liczyliśmy tu w grupie multiplikatywnej modulo 2323, a nie na krzywej: gSg^S odpowiada SBS\cdot B, a iloczyn RAkR\cdot A^k — dodawaniu punktów R+kAR + k\cdot A. Struktura jest ta sama i właśnie o to chodzi. Różnią się rzędy wielkości: =11\ell = 11 wobec 2252\ell \approx 2^{252}, a tam klucza nie znajdzie się przez wypróbowanie jedenastu możliwości.


14. Co się dzieje, gdy ktoś zmieni opinię

Załóżmy, że ktoś z dostępem do bazy danych — także ktoś u nas — zmienia tekst opinii albo jedno z serduszek. Wtedy zmienia się rekord danych, a wraz z nim co najmniej jedna z dwóch wartości skrótu h i rh w payloadzie. Tym samym zmienia się mm, więc challenge kk, więc prawa strona równania weryfikacyjnego. Stary podpis już nie pasuje.

Rozstrzygające zdanie brzmi: opinię możemy usunąć, ale nie możemy jej zmienić niepostrzeżenie. W McGesund ta sama weryfikacja przebiega dodatkowo co noc po stronie serwera na całym zasobie — opinia, która jej nie przejdzie, nie wlicza się już do średniej firmy.


15. Dlaczego atakujący przegrywa

Zna klucz publiczny AA, punkt bazowy BB, krzywą i każdy dotąd wystawiony podpis. Brakuje mu aa.

Najlepszy znany klasyczny atak na problem logarytmu dyskretnego w grupie rzędu \ell potrzebuje około \sqrt{\ell} kroków. Przy 2252\ell \approx 2^{252} to mniej więcej

21262^{126}

operacji. Dla porównania: nawet maszyna wykonująca miliard miliardów (101810^{18}) kroków na sekundę potrzebowałaby na to wielokrotności wieku wszechświata.

Fałszowanie bez klucza oznaczałoby znalezienie do samodzielnie wybranego kk pasującego SS — to samo zadanie w innym przebraniu.


16. Dlaczego Ed25519, a nie ECDSA

Oba opierają się na tym samym problemie. Różnica leży we wszystkim, co dzieje się dookoła:

ECDSA (krzywe NIST)Ed25519
Noncepotrzebna świeża losowośćdeterministyczny z prefiksu i wiadomości
Wzoryprzypadki szczególne, gałęzie zależne od danychzupełne, jedna droga obliczeń
Parametry krzywejpochodzenie stałych nigdy w pełni wyjaśnionewybrane według jawnych kryteriów
Rozmiar podpisu64–72 B, zmienne kodowaniestałe 64 B
W przeglądarcedostępny od dawnanatywnie od 2023/2024, poza tym jako biblioteka JS

Dla nas rozstrzygający był nonce. Portal z opiniami podpisuje często i automatycznie; metoda, w której jedna słaba wartość losowa ujawnia klucz, jest do tego złym wyborem.


17. Czego Ed25519 nie zapewnia

Ed25519 opiera się na logarytmie dyskretnym — a właśnie ten problem dostatecznie duży komputer kwantowy rozwiązuje efektywnie algorytmem Shora. Czy i kiedy takie maszyny powstaną, pozostaje otwarte. Dla opinii, która ma być sprawdzalna jeszcze za dziesięć lat, jest to mimo wszystko pytanie, na które trzeba odpowiedzieć już dziś.

Dlatego obok podpisu Ed25519 może stanąć stempel odporny na ataki kwantowe:

Żaden z nich nie zastępuje Ed25519, kładą się obok. Jeśli jedna z metod padnie, druga niesie dowód dalej.


18. Przebieg na rysunku

USŁUGA PODPISUJĄCA (MCGESUND)PRZEGLĄDARKA ODWIEDZAJĄCEGOprywatny skalar a + prefiks (z seeda)payload m = {firma, opinia, h, rh, iat}r = H(prefiks ‖ m) mod ℓR = r · Bk = H(R ‖ A ‖ m) mod ℓS = (r + k · a) mod ℓpodpis σ = (R, S) + kidopinia + σ + klucz publiczny Aprzeliczenie k z R, A i mS · B = R + k · A ?ważnynieważny
Od payloadu po znacznik potwierdzenia w przeglądarce. Powyżej linii podziału wszystko dzieje się raz, przy wysłaniu, poniżej — na nowo u każdego czytelnika, na jego urządzeniu, wyłącznie z kluczem publicznym.

19. Co konkretnie robi z tym McGesund

Koperta. Każda podpisana opinia niesie kopertę MCG1: z wersją formatu, payloadem i podpisem Ed25519. kid w payloadzie mówi, o który klucz chodzi; odpowiadający mu klucz publiczny serwer wydaje na żądanie — jest publiczny, nie ma tam czego chronić.

Weryfikacja w przeglądarce. Chrome i Firefox obsługują Ed25519 natywnie od 2023/2024 przez interfejs WebCrypto. Safari nie — tam wywołanie zgłasza błąd zamiast weryfikować. Dlatego nasz kod weryfikujący sięga po czystą implementację w JavaScripcie, doładowywaną tylko tam, gdzie jest potrzebna. Weryfikacja podpisu przechodzi dzięki temu w każdej przeglądarce, i to na urządzeniu czytelnika.

Kotwica czasu. Odcisk klucza podpisującego zostaje zakotwiczony przez OpenTimestamps w bloku Bitcoina. Pozwala to wykazać nie tylko, że podpis jest prawdziwy, lecz także, że klucz istniał już w określonym momencie — bez konieczności wiary komukolwiek w nasz znacznik czasu.

Powiązanie z treścią. Payload niesie rh, skrót całego rekordu przesłanej opinii: tekstu, serduszek, statusu geolokalizacji, informacji o okoliczności i pochodzenia. Podpis Ed25519 wiąże tym samym nie tylko tekst, lecz wszystko, co wyświetla się obok opinii.


20. Jedno zdanie na wynos

Ed25519 zamienia tajną liczbę w roˊwnanie,ktoˊre kaz˙dy moz˙e przeliczycˊ i nikt wymysˊlicˊ.\boxed{ \begin{array}{c} \text{Ed25519 zamienia tajną liczbę w równanie,}\\ \text{które każdy może przeliczyć i nikt wymyślić.} \end{array}}

Kto posiada tajny skalar, podpisuje w mikrosekundach. Kto go nie posiada, musiałby rozwiązać logarytm dyskretny w grupie o około 22522^{252} elementach.

Dla czytelnika opinii oznacza to po prostu: nie musi nam wierzyć. Może przeliczyć.