Wrocław University of Science and TechnologyDepartment of Fundamentals of Computer Science

Kryptografia II stopień

Od definicji bezpieczeństwa do konstrukcji, redukcji i publikacji naukowych.

W9. Podpisy, Fiat–Shamir i BLS

Nowa potrzeba: odbiorca nie uczestniczy w rozmowie w chwili tworzenia dokumentu. Chcemy zostawić wiadomość i obiekt, który sprawdzi później. Dlatego zastępujemy żywą rozmowę dwoma lokalnymi algorytmami: Sign u autora oraz Verify u odbiorcy. Weryfikacja nie wymaga ponownego połączenia z autorem.

Podpis nie jest zapisem dowolnej udanej identyfikacji. Taki zapis uczciwego Schnorra potrafi stworzyć poznany symulator. Potrzebujemy dodatkowego związania wyzwania z wiadomością. Pokaże je transformata Fiata–Shamira. Podpisy cyfrowe jako ogólna rodzina nie są z definicji nieinteraktywnymi dowodami z wiedzą zerową. W Schnorrze wykorzystujemy związek z dowodem znajomości sekretu i analizą w modelu wyroczni losowej. Własność podpisu, którą musimy następnie udowodnić, to niepodrabialność. W odróżnieniu od symulowalnego zapisu identyfikacji podpis jest przeznaczony do publicznego przekazywania i sprawdzania.

Podpis umożliwia publiczną weryfikację wiadomości. W EUF-CMA przeciwnik może uzyskać podpisy wybranych wiadomości, a wygrywa przez podpis nowej. Silna niepodrabialność dodatkowo wyklucza nowy podpis wiadomości już podpisanej.

Rozwinięcie skrótu EUF-CMA to existential unforgeability under chosen-message attack. „Egzystencjalne” oznacza, że wystarczy dowolna nowa wiadomość spełniająca warunek gry. Atak nie musi podrabiać konkretnego dokumentu wybranego przez audytora. „Wybrane wiadomości” oznaczają dostęp do podpisywania przed zakończeniem ataku. Weryfikacja podpisu jest publiczna, więc nie musimy ukrywać jej za tajną wyrocznią.

Podpis cyfrowy: Setup, KeyGen, Sign, Verify

Wracamy do kontraktu wprowadzonego na początku. Sign korzysta z klucza tajnego, a Verify z właściwego klucza publicznego. Wymaganie, aby przeciwnik nie tworzył nowych akceptowanych podpisów, jest osobną definicją niepodrabialności. Schemat zapisujemy jako:

Πsig=(Setup,KeyGen,Sign,Verify).\Pi_{\mathrm{sig}}=(\mathsf{Setup},\mathsf{KeyGen},\mathsf{Sign},\mathsf{Verify}).
Algorytm i jego wynik Wejście Co wykonuje i komu służy
pp←Setup(1λ)pp\leftarrow\mathsf{Setup}(1^\lambda) Parametr bezpieczeństwa Ustala jawne parametry, kodowania i przestrzeń wiadomości.
(pk,sk)←KeyGen(pp)(pk,sk)\leftarrow\mathsf{KeyGen}(pp) Parametry publiczne Podpisujący tworzy powiązaną parę kluczy.
σ←Sign(pp,sk,m)\sigma\leftarrow\mathsf{Sign}(pp,sk,m) Parametry, klucz tajny i wiadomość Tworzy podpis σ\sigma z określonej przestrzeni podpisów Spp\mathcal S_{pp}.
b←Verify(pp,pk,m,σ)b\leftarrow\mathsf{Verify}(pp,pk,m,\sigma) Parametry, klucz publiczny, wiadomość i podpis Zwraca bit: 1 oznacza akceptację, 0 odrzucenie, także niepoprawnego formatu.

Sign znaczy podpisz, a Verify sprawdź. W tym kursie opisujemy podpis z dołączoną wiadomością: weryfikator otrzymuje zarówno mm, jak i σ\sigma. Nie odzyskuje dokumentu z samego podpisu. W ogólnym interfejsie zakładamy, że Sign może wyznaczyć odpowiadający klucz publiczny z klucza tajnego i parametrów. Tam, gdzie potrzebne są dodatkowe jawne dane, zaznaczamy je w opisie konkretnego klucza.

Przy doskonałej poprawności dla każdych parametrów i pasującej pary kluczy zwracanych przez Setup oraz KeyGen wymagamy:

Pr⁡[Verify(pp,pk,m,Sign(pp,sk,m))=1]=1dla kaz˙dego m∈Mpp.\Pr[\mathsf{Verify}(pp,pk,m,\mathsf{Sign}(pp,sk,m))=1]=1 \quad\text{dla każdego }m\in\mathcal M_{pp}.

Prawdopodobieństwo w tym wzorze dotyczy losowości Sign przy ustalonych parametrach, kluczach i wiadomości. Sign może być losowy, jak w omawianym Schnorrze, albo deterministyczny, jak w podstawowym BLS przy ustalonym haszu. Verify jest tutaj deterministyczny. Niepodrabialność będzie mówiła o tworzeniu nowych akceptowanych podpisów przez przeciwnika. Nie wynika z samego równania poprawności.

Gdzie wykonuje się Sign

Użytkownik przekazuje urządzeniu dokładne bajty mm. Urządzenie odnajduje uprawniony klucz sksk i uruchamia σ←Sign(pp,sk,m)\sigma\leftarrow\mathsf{Sign}(pp,sk,m). Na zewnątrz zwraca podpis. To, że algorytm ma klucz wśród argumentów, nie oznacza wysyłania klucza do odbiorcy ani konieczności przekazywania go przy każdym wywołaniu przez aplikację. W API urządzenia aplikacja może podawać identyfikator klucza przechowywanego wewnątrz.

Aplikacja autora
pp,mpp,m
Urządzenie: Sign
σ←Sign(pp,sk,m)\sigma\leftarrow\mathsf{Sign}(pp,sk,m)
wywołaniePrzesyłane lub zapisane dane
(m,σ)(m,\sigma)
klucz tajny pozostaje w urządzeniuOdbiorca: Verify
b=Verify(pp,pk,m,σ)b=\mathsf{Verify}(pp,pk,m,\sigma)
Wynik dla aplikacji1: akceptacja, 0: odrzucenieOdczyt w późniejszym czasieOdbiorca ma zaufany klucz publiczny.Autor nie uczestniczy w Verify.
Schemat podpisu oddziela tworzenie artefaktu od jego sprawdzania. Parametry pppp i zaufany pkpk są znane weryfikatorowi. Klucz sksk pozostaje u autora. Strzałki pokazują wywołania i przekazanie danych, nie wysyłanie wszystkich argumentów przez sieć.

Do sprawdzenia potrzebne są pp,pk,m,σpp,pk,m,\sigma. Jeśli odbiorca nie ma wiarygodnego powiązania pkpk z autorem, poprawne Verify potwierdza zgodność podpisu z tym kluczem, ale nie nazwisko autora. Ustalenie tego powiązania, kontrola uprawnień i ochrona urządzenia są częścią systemu otaczającego schemat.

Podpis Schnorra

Z rozmowy identyfikacyjnej przechodzimy do schematu ΠSch=(Setup,KeyGen,Sign,Verify)\Pi_{\mathrm{Sch}}=(\mathsf{Setup},\mathsf{KeyGen},\mathsf{Sign},\mathsf{Verify}). W tym dydaktycznym profilu podpis ma postać pary σ=(X,s)\sigma=(X,s). Element XX jest zobowiązaniem, a skalar ss odpowiedzią. Wiadomość mm dostarczamy do Verify oddzielnie.

Podpis Schnorra: algorytmy i przepływ

Setup dołącza skalarny hasz ℋ oraz jednoznaczne kodowanie. Zaufany klucz publiczny jest znany przed Verify. Wiadomość m jest ciągiem bajtów.

Π=(Setup,KeyGen,Sign,Verify)\Pi=(\mathsf{Setup},\mathsf{KeyGen},\mathsf{Sign},\mathsf{Verify})
Setup(1λ)\mathsf{Setup}(1^\lambda)⟶pp\longrightarrow pp
pp=(G,q,g,ℋ,enc⁡)pp=(G,q,g,\mathcal H,\operatorname{enc})
ℋ:{0,1}∗→Zq\mathcal H:\{0,1\}^*\to\mathbb Z_q

G ma pierwszy rząd q i generator g. Ustal jednoznaczne kodowanie i separator domeny Schnorr.

KeyGen(pp)\mathsf{KeyGen}(pp)⟶(A,a)\longrightarrow (A,a)
a←$Zq,A=gaa\overset{\$}{\leftarrow}\mathbb Z_q,\quad A=g^a

Profil z całym ciałem, zgodnie z opisem konstrukcji. Sekret a pozostaje u właściciela. Odbiorca uwierzytelnia publiczny A.

Sign(pp,a,m)\mathsf{Sign}(pp,a,m)⟶σ=(X,s)\longrightarrow \sigma=(X,s)
A=gaA=g^a
u←$Zq,X=guu\overset{\$}{\leftarrow}\mathbb Z_q,\quad X=g^u
c=ℋ(enc⁡(Schnorr,A,X,m))c=\mathcal H(\operatorname{enc}(\mathtt{Schnorr},A,X,m))
s=u+a⋅c(modq)s=u+a\cdot c\pmod q
Verify(pp,A,m,(X,s))\mathsf{Verify}(pp,A,m,(X,s))⟶b∈{0,1}\longrightarrow b\in\{0,1\}
c=ℋ(enc⁡(Schnorr,A,X,m))c=\mathcal H(\operatorname{enc}(\mathtt{Schnorr},A,X,m))
b=[gs=X⋅Ac]b=[g^s=X\cdot A^c]

Przed równaniem sprawdź klucz, X i s.

Podpis Schnorra: czynności i komunikatyPodpisującyWeryfikatorSign: zobowiązanieSign: wyzwanie i odpowiedźZapis lub przesłanie podpisanego dokumentuVerify: samodzielne odtworzenie

Podpis Schnorra

Podpisujący: pp,a,mpp,a,m

Weryfikator: pp,App,A

  1. Podpisujący, Sign: zobowiązanie: A=ga,u←$ZqA=g^a,\quad u\overset{\$}{\leftarrow}\mathbb Z_q X=guX=g^u
  2. Podpisujący, Sign: wyzwanie i odpowiedź: c=ℋ(enc⁡(Schnorr,A,X,m))c=\mathcal H(\operatorname{enc}(\mathtt{Schnorr},A,X,m)) s=u+a⋅c(modq)s=u+a\cdot c\pmod q
  3. Podpisujący → Weryfikator: (m,σ=(X,s))(m,\sigma=(X,s)) Zapis lub przesłanie podpisanego dokumentu
  4. Weryfikator, Verify: samodzielne odtworzenie: c=ℋ(enc⁡(Schnorr,A,X,m))c=\mathcal H(\operatorname{enc}(\mathtt{Schnorr},A,X,m)) gs=?X⋅Acg^s\stackrel{?}{=}X\cdot A^c
Nie ma wiadomości zwrotnej z wyzwaniem. Sign i Verify osobno obliczają tę samą funkcję haszującą.

Setup: grupa i hasz Schnorra

Wejście: 1λ1^\lambda. Wyjście: pp=(G,q,g,ℋ,enc⁡)pp=(G,q,g,\mathcal H,\operatorname{enc}). Grupa GG ma pierwszy rząd qq i generator gg. Funkcja ℋ:{0,1}∗→Zq\mathcal H:\{0,1\}^*\to\mathbb Z_q zwraca skalar. Kodowanie enc⁡\operatorname{enc} jednoznacznie zapisuje typy i granice pól. Ustalamy także separator domeny Schnorr\mathtt{Schnorr}. Parametry i oznaczenie profilu są wspólne dla podpisującego oraz weryfikatora. Późniejszy dowód analizuje ℋ\mathcal H w modelu wyroczni losowej.

KeyGen: klucze podpisującego

Wejście: pppp. Losujemy a←$Zqa\overset{\$}{\leftarrow}\mathbb Z_q i obliczamy A=gaA=g^a. Wyjście: (pk,sk)=(A,a)(pk,sk)=(A,a). Małe aa jest tajnym skalarem, a duże AA publicznym elementem grupy. To te same role co w protokole identyfikacji, ale inny interfejs niż w szyfrowaniu. Sign używa aa, a Verify używa AA.

Sign: tworzenie podpisu

Wejście: pppp, klucz tajny aa i wiadomość m∈{0,1}∗m\in\{0,1\}^*. Algorytm wyznacza odpowiadający klucz publiczny A=gaA=g^a. Następnie:

  1. Losuje świeże u←$Zqu\overset{\$}{\leftarrow}\mathbb Z_q i oblicza X=guX=g^u.
  2. Oblicza c=ℋ(enc⁡(Schnorr,A,X,m))c=\mathcal H(\operatorname{enc}(\mathtt{Schnorr},A,X,m)).
  3. Oblicza s=u+c⋅amodqs=u+c\cdot a\bmod q.
  4. Zwraca σ=(X,s)∈G×Zq\sigma=(X,s)\in G\times\mathbb Z_q.

Skalar uu nie jest częścią podpisu i nie może być ponownie używany w innym podpisywaniu. Wartość cc będzie odtworzona z jawnych danych, więc w tym formacie nie trzeba jej przesyłać.

Verify: sprawdzanie podpisu

Wejście: pppp, klucz publiczny AA, wiadomość mm i podpis σ\sigma. Sprawdzamy jednoznaczny format oraz typy A,X∈GA,X\in G i s∈Zqs\in\mathbb Z_q. Błędne wejście daje 0. Dla poprawnego formatu obliczamy ponownie cc z tych samych czterech argumentów i zwracamy:

Verify(pp,A,m,(X,s))={1gdy gs=X⋅Ac,0w przeciwnym razie.\mathsf{Verify}(pp,A,m,(X,s))= \begin{cases} 1&\text{gdy }g^s=X\cdot A^c,\\ 0&\text{w przeciwnym razie.} \end{cases}

Algorytm nie otrzymuje aa ani uu. Nie ufa wartości cc podanej przez inną stronę.

Poprawność i przejście z identyfikacji

Dla podpisu zwróconego przez Sign zachodzi:

gs=gu+c⋅a=gu⋅(ga)c=X⋅Ac.g^s=g^{u+c\cdot a}=g^u\cdot(g^a)^c=X\cdot A^c.

To dowód poprawności. Niepodrabialność wymaga osobnego dowodu z symulacją i forking lemma. Zgodnie z tym opisem losujemy z Zq\mathbb Z_q. Klucz a=0a=0 jest degeneracją o prawdopodobieństwie 1/q1/q. Profil odrzucający taki klucz musi jawnie zmienić regułę KeyGen, nie samo równanie Verify.

Weryfikator nie wysyła już losowego wyzwania. Sam wylicza je z klucza, zobowiązania i wiadomości. Podpisujący musi więc najpierw ustalić zobowiązanie, następnie policzyć hasz, a dopiero potem odpowiedź. Dziedzina oznaczona napisem Schnorr rozdziela to zastosowanie od innych protokołów korzystających z podobnych obiektów.

Dwa formaty tego samego podpisu

W powyższym formacie przesyłamy (X,s)(X,s), a weryfikator oblicza cc. Można zamiast tego przesłać (s,c)(s,c) i odzyskać zobowiązanie. Klucz publiczny nadal wynosi A=gaA=g^a. Dla tego samego kodowania i tej samej etykiety domeny weryfikator wykonuje:

X′=gs⋅A−c,c′=ℋ(enc⁡(Schnorr,A,X′,m)),Verify(pp,A,m,(s,c))=[c′=c].\begin{aligned} X'&=g^s\cdot A^{-c},\\ c'&=\mathcal H(\operatorname{enc}(\mathtt{Schnorr},A,X',m)),\\ \mathsf{Verify}(pp,A,m,(s,c))&=[c'=c]. \end{aligned}

Nawias kwadratowy oznacza bit wyniku porównania. Przed tym rachunkiem sprawdzamy parametry, dozwoloną podgrupę klucza oraz kanoniczne kodowanie skalarów s,c∈{0,…,q−1}s,c\in\{0,\ldots,q-1\}. Stosujemy te same reguły dopuszczalności klucza i zobowiązania co w wybranym profilu Sign. Nie wystarczy obliczyć X′X' i ogłosić sukcesu. Dla dowolnych skalarów da się obliczyć jakiś element grupy. Dopiero ponowne obliczenie hasza i porównanie c′=cc'=c wiąże wynik z wiadomością.

W realizacji addytywnej A=a⋅PA=a\cdot P i X′=s⋅P−c⋅AX'=s\cdot P-c\cdot A. Przy uczciwym podpisie odtwarzamy dokładnie pierwotne XX, więc oba formaty prowadzą do tego samego wejścia hasza. Zadania C6.6 i L4.7 pozwalają porównać liczbę przesyłanych bajtów i działania Verify. Zmiana formatu nie jest nową gwarancją bezpieczeństwa i nie uzasadnia zmiany dziedziny hasza między implementacjami.

Ataki na błędne warianty hasza

Pominięcie zobowiązania.

Celowo błędny wariant wylicza c=ℋ(m)c=\mathcal H(m), pomijając XX. Przeciwnik zna wtedy cc przed ustaleniem zobowiązania. Wybiera dowolne ss i oblicza:

X=gs⋅A−c.X=g^s\cdot A^{-c}.

Oddaje (X,s)(X,s). Weryfikacja przechodzi dla wiadomości mm. Nie znalazł kolizji hasza i nie poznał klucza. Konstrukcja pozwoliła mu rozwiązać równanie w niewłaściwej kolejności. Powrót do związania zobowiązania zamyka tę prostą strategię, ale pełny dowód nadal wymaga symulacji zapytań i argumentu forking.

„Hasz” o zbyt prostej algebrze.

Rozważmy inną, jawnie błędną funkcję ℋbad(X,m)=enc⁡(X)+mmodq\mathcal H_{\mathrm{bad}}(X,m)=\operatorname{enc}(X)+m\bmod q, gdzie wiadomości są skalarami, a kodowanie publiczne. Z podpisu (X0,s0)(X_0,s_0) wiadomości m0m_0 przeciwnik wybiera rr i tworzy:

X1=X0⋅gr,m1=m0+enc⁡(X0)−enc⁡(X1),s1=s0+r.\begin{aligned} X_1&=X_0\cdot g^r,\\ m_1&=m_0+\operatorname{enc}(X_0)-\operatorname{enc}(X_1),\\ s_1&=s_0+r. \end{aligned}

Nowe wyzwanie jest równe poprzedniemu, więc równanie podpisu nadal zachodzi. Aby spełnić warunek nowej wiadomości, trzeba uzyskać m1≠m0m_1\ne m_0. Atak pokazuje znaczenie struktury funkcji, nie ogólną wadę dodawania w ciele. W poprawnym podpisie używamy właściwej funkcji z właściwym modelem, a nie dowolnego kodowania nazwanego haszem.

Zbyt krótkie wyzwanie.

Jeśli wyzwanie ma tylko hh możliwych wartości, oszust może zgadywać cc, wybierać ss, tworzyć X=gs⋅A−cX=g^s\cdot A^{-c} i sprawdzać, czy hasz zwrócił zgadnięte cc. Dla świeżych wejść w idealnym modelu prawdopodobieństwo trafienia wynosi 1/h1/h na próbę. Mała przestrzeń wyzwań osłabia podpis niezależnie od rozmiaru grupy.

To nie ten sam rachunek co poszukiwanie dowolnej kolizji hasza z kosztem urodzinowym. Tutaj trzeba trafić określoną wartość po ustaleniu związanej z nią reszty danych. Zanim użyjesz pierwiastka z rozmiaru przestrzeni, nazwij dokładnie zdarzenie, którego szukasz.

Hash wiąże wiadomość, klucz i zobowiązanie. Model wyroczni losowej idealizuje hash. Redukcja może programować odpowiedzi pod warunkami tego modelu. Implementacja nie ma programowalnego SHA.

Forking lemma służy otrzymaniu drugiego kompatybilnego wykonania ze zmienionym wyzwaniem. Nie gwarantuje sukcesu. Symulację i straty wyprowadzamy w pogłębieniu dowodowym.

Podpis BLS

W BLS podpis jest jednym elementem grupy, zamiast pary zobowiązanie–odpowiedź. Nadal mamy ten sam ogólny interfejs ΠBLS=(Setup,KeyGen,Sign,Verify)\Pi_{\mathrm{BLS}}=(\mathsf{Setup},\mathsf{KeyGen},\mathsf{Sign},\mathsf{Verify}). Zmieniają się typ podpisu i sposób sprawdzania. Poniżej opisujemy pojedynczy podpis, nie agregację podpisów.

Podpis BLS: algorytmy i przepływ

Π=(Setup,KeyGen,Sign,Verify)\Pi=(\mathsf{Setup},\mathsf{KeyGen},\mathsf{Sign},\mathsf{Verify})
Setup(1λ)\mathsf{Setup}(1^\lambda)⟶pp\longrightarrow pp
pp=(q,G1,G2,GT,e,g2,ℋG1)pp=(q,G_1,G_2,G_T,e,g_2,\mathcal H_{G_1})
e:G1×G2→GTe:G_1\times G_2\to G_T
ℋG1:{0,1}∗→G1\mathcal H_{G_1}:\{0,1\}^*\to G_1

Grupy mają wspólny pierwszy rząd q. Ustal generator g₂, kodowania i separator domeny hash-to-group.

KeyGen(pp)\mathsf{KeyGen}(pp)⟶(A2,a)\longrightarrow (A_2,a)
a←$Zq∗,A2=g2aa\overset{\$}{\leftarrow}\mathbb Z_q^*,\quad A_2=g_2^a
Sign(pp,a,m)\mathsf{Sign}(pp,a,m)⟶σ∈G1\longrightarrow \sigma\in G_1
Q=ℋG1(m),σ=QaQ=\mathcal H_{G_1}(m),\quad\sigma=Q^a
Verify(pp,A2,m,σ)\mathsf{Verify}(pp,A_2,m,\sigma)⟶b∈{0,1}\longrightarrow b\in\{0,1\}
Q=ℋG1(m)Q=\mathcal H_{G_1}(m)
b=[e(σ,g2)=e(Q,A2)]b=[e(\sigma,g_2)=e(Q,A_2)]

Sprawdź podgrupy, kodowania i niezerowy klucz.

Podpis BLS: czynności i komunikatyPodpisującyWeryfikatorSign: hash do grupySign: działanie sekretemPodpis jest jednym elementem G₁Verify

Podpis BLS

Podpisujący: pp,a,mpp,a,m

Weryfikator: pp,A2pp,A_2

  1. Podpisujący, Sign: hash do grupy: Q=ℋG1(m)∈G1Q=\mathcal H_{G_1}(m)\in G_1
  2. Podpisujący, Sign: działanie sekretem: σ=Qa\sigma=Q^a
  3. Podpisujący → Weryfikator: (m,σ)(m,\sigma) Podpis jest jednym elementem G1
  4. Weryfikator, Verify: Q=ℋG1(m)Q=\mathcal H_{G_1}(m) e(σ,g2)=?e(Q,A2)e(\sigma,g_2)\stackrel{?}{=}e(Q,A_2)
Pairing występuje przy Verify. Hash-to-group nie ujawnia znanego skalaru względem ustalonej bazy.

Setup: grupy i hash do punktu

Wejście: 1λ1^\lambda. Wyjście: pp=(q,G1,G2,GT,e,g2,ℋG1)pp=(q,G_1,G_2,G_T,e,g_2,\mathcal H_{G_1}) wraz z kodowaniami i separatorem domeny hasza. Grupy mają ten sam pierwszy rząd qq. Pairing e:G1×G2→GTe:G_1\times G_2\to G_T jest biliniowy i niezdegenerowany, a g2g_2 generuje G2G_2. Funkcja ℋG1:{0,1}∗→G1\mathcal H_{G_1}:\{0,1\}^*\to G_1 poprawnie haszuje wiadomość do grupy, w uzgodnionym profilu haszowania. Nie jest jawnym kodowaniem do skalaru pomnożonego przez stałą bazę.

KeyGen: sekret i klucz w drugiej grupie

Wejście: pppp. Losujemy niezerowe a←$Zq∗a\overset{\$}{\leftarrow}\mathbb Z_q^* i obliczamy A2=g2aA_2=g_2^a. Wyjście: (pk,sk)=(A2,a)(pk,sk)=(A_2,a). Publiczny A2A_2 należy do G2G_2. Podpis będzie należał do G1G_1. W podstawowym wariancie nie trzeba publikować drugiego klucza w G1G_1.

Sign: haszowanie i działanie sekretem

Wejście: pppp, klucz tajny aa oraz wiadomość m∈{0,1}∗m\in\{0,1\}^*. Wyznaczamy Q=ℋG1(m)Q=\mathcal H_{G_1}(m) i zwracamy σ=Qa∈G1\sigma=Q^a\in G_1. Przy ustalonym kluczu i profilu hasza wynik jest deterministyczny. Nie losujemy osobnego nonce jak w Schnorrze.

Verify: równanie parowań

Wejście: pppp, klucz publiczny A2A_2, wiadomość mm i podpis σ\sigma. Sprawdzamy kodowania i przynależność do podgrup A2∈G2A_2\in G_2 oraz σ∈G1\sigma\in G_1. Odrzucamy neutralny klucz publiczny. Dla błędnego wejścia zwracamy 0. W przeciwnym razie samodzielnie liczymy Q=ℋG1(m)Q=\mathcal H_{G_1}(m) i zwracamy 1 wtedy i tylko wtedy, gdy:

e(σ,g2)=e(Q,A2).e(\sigma,g_2)=e(Q,A_2).

Argumenty pairingu mają ustaloną kolejność: najpierw element G1G_1, potem element G2G_2. Weryfikator nie potrzebuje sekretu aa.

Poprawność, notacja i demonstrator

Podpis i jego kontrola mają prosty zapis potęgowy:

σ=ℋG1(m)a,e(σ,g2)=e(ℋG1(m),A2).\sigma=\mathcal H_{G_1}(m)^a,\qquad e(\sigma,g_2)=e(\mathcal H_{G_1}(m),A_2).

Obie strony są równe e(ℋG1(m),g2)ae(\mathcal H_{G_1}(m),g_2)^a. Hasz daje element grupy, nie jawny skalar do pomnożenia przez stały generator. Potęgowanie hasza oznacza tu działanie sekretnego skalara na otrzymanej bazie. W implementacji na krzywej ta sama operacja nosi nazwę mnożenia skalarnego.

W addytywnych grupach źródłowych σ=a⋅ℋG1(m)\sigma=a\cdot\mathcal H_{G_1}(m), A2=a⋅P2A_2=a\cdot P_2. Sprawdzamy:

e(σ,P2)=e(ℋG1(m),A2).e(\sigma,P_2)=e(\mathcal H_{G_1}(m),A_2).

Multiplikatywnie zapisujemy σ=ℋG1(m)a\sigma=\mathcal H_{G_1}(m)^a. To mnożenie punktu przez skalar zapisane potęgą, nie potęgowanie współrzędnych.

Gdy wariant używa także A1=a⋅P1A_1=a\cdot P_1, zgodność reprezentacji sprawdza e(A1,P2)=e(P1,A2)e(A_1,P_2)=e(P_1,A_2). Podstawowy wariant nie musi publikować obu. Grupy źródłowe nie są zamienne w API.

BLS · podpis i weryfikacja pairingowa

MCL WebAssembly, BLS12-381. Podpis w G1 i klucz publiczny w G2. Lokalne hashAndMapToG1, nie deklaracja standardowej ciphersuite.

Zapis i obliczenia. Wzory schematu są multiplikatywne. MCL realizuje je na krzywej. Generatory g1,g2g_1,g_2 odpowiadają punktom P1,P2P_1,P_2. W grupach punktów iloczyn oznacza dodawanie, potęga oznacza mnożenie punktu przez skalar, a odwrotność oznacza punkt przeciwny. Nie potęgujemy współrzędnych. Ten schemat używa również pairingu. W grupie docelowej zapis pozostaje multiplikatywny.

Gotowe do rozpoczęcia.

Błędny zamiennik: ℋbad(m)=h(m)⋅P1\mathcal H_{\mathrm{bad}}(m)=h(m)\cdot P_1 dla znanego publicznie h(m)h(m). Z podpisu dla h(m)≠0h(m)\ne0 odzyskujemy a⋅P1a\cdot P_1 i tworzymy podpis każdej wiadomości. Poprawny hash do grupy nie ujawnia tak znanego logarytmu.

Demonstrator używa hashAndMapToG1 MCL. Nie deklaruje standardowego formatu BLS ani konkretnego zestawu RFC 9380. Bada pojedyncze podpisy. Agregacja wymaga dodatkowych warunków, np. ochrony przed rogue-key attacks.

Pełna ścieżka dowodowa: Schnorr: symulator, fork i redukcja DL, Okamoto: podpis i dwie reprezentacje. Najpierw przeczytaj definicję EUF-CMA powyżej. Rozdziały dowodowe podają założenia, wszystkie interfejsy oraz straty prawdopodobieństwa.

Powiązania: C6, L4, Boneh–Lynn–Shacham, RFC 9380.

W10. Ustalanie kluczy: DH, SIGMA i NAXOS

NAXOS
NAXOS. Nazwa własna protokołu uwierzytelnionej wymiany klucza, nie skrót rozwijany do angielskich słów.

Nowa potrzeba: nie wystarczy rozpoznać rozmówcy ani podpisać dokumentu. Dwie strony chcą uzyskać ten sam świeży sekret do ochrony kolejnych wiadomości i wiedzieć, z kim go współdzielą. Uzgodnienie klucza jest protokołem. Podpis jest jednym z możliwych narzędzi jego uwierzytelniania, a nie kompletnym protokołem wymiany.

Interfejs AKE: klucze długoterminowe i stan sesji

AKE, authenticated key exchange, oznacza uwierzytelnione uzgadnianie klucza. Dla omawianych systemów z kluczami publicznymi uporządkujemy opis jako

ΠAKE=(Setup,KeyGen,Start,Next).\Pi_{\mathrm{AKE}}=(\mathsf{Setup},\mathsf{KeyGen},\mathsf{Start},\mathsf{Next}).

Jest to wspólny interfejs dydaktyczny dla maszyny stanów protokołu. Publikacje mogą grupować te czynności inaczej. Nie jest to twierdzenie, że każdy protokół AKE ma identyczne komunikaty lub korzysta z podpisów. W SIGMA KeyGen przygotuje klucze podpisu, a w NAXOS klucze dla działań grupowych. Inne rodziny AKE mogą używać współdzielonego sekretu lub hasła.

Niech ID\mathrm{ID} oznacza lokalną tożsamość, peer\mathrm{peer} zamierzonego partnera, a role\mathrm{role} rolę inicjatora lub odpowiadającego. Stan stst zawiera m.in. klucz długoterminowy lub odwołanie do niego, świeże sekrety sesji, dotychczasowe komunikaty i etap protokołu. Bufor outout zawiera komunikat do wysłania, a inin komunikat otrzymany. Pusty bufor zapisujemy jako ε\varepsilon.

Wywołanie Wynik i znaczenie
pp←Setup(1λ)pp\leftarrow\mathsf{Setup}(1^\lambda) Profil grup, algorytmów, kodowań i długości kluczy.
(pk,sk)←KeyGen(pp)(pk,sk)\leftarrow\mathsf{KeyGen}(pp) Długoterminowe klucze uczestnika. Rejestracja wiąże jego tożsamość z pkpk.
(st,out)←Start(pp,ID,sk,peer,role)(st,out)\leftarrow\mathsf{Start}(pp,\mathrm{ID},sk,\mathrm{peer},\mathrm{role}) Nowy prywatny stan oraz pierwszy komunikat albo ε\varepsilon. Weryfikowane klucze partnerów uzyskujemy z uzgodnionego mechanizmu rejestracji.
(st′,out,status,K)←Next(st,in)(st',out,status,K)\leftarrow\mathsf{Next}(st,in) Kolejny stan, odpowiedź do sieci i status: kontynuacja, odrzucenie lub akceptacja. K=⊥K=\bot oznacza, że aplikacja nie otrzymuje jeszcze klucza. Przy akceptacji otrzymuje K∈{0,1}ℓK\in\{0,1\}^{\ell} o długości ustalonej przez profil.

Klucz wewnętrznie obliczony z otrzymanych punktów nie jest automatycznie kluczem zaakceptowanej sesji. Najpierw muszą przejść kontrole wymagane przez protokół. Wywołanie Next odrzuca także komunikat w niewłaściwym formacie lub niedozwolony na danym etapie. Po zakończeniu nie kontynuuje tej samej sesji z nowymi komunikatami.

Poprawność: jeśli uczciwi, zgodnie skonfigurowani partnerzy wykonają cały protokół i otrzymają wymagane komunikaty, akceptują zgodny klucz oraz właściwego partnera. Bezpieczeństwo: w określonym modelu aktywnej sieci przeciwnik nie powinien rozpoznać klucza świeżej sesji ani naruszyć wymaganej gwarancji uwierzytelnienia. Dokładne reguły partnerowania i ujawnień są częścią definicji. Nie wyprowadza się ich z samej równości dwóch kluczy.

Rdzeń DH i atak pośrednika

W DH Alicja wysyła X=gxX=g^x, Bob Y=gyY=g^y, a oboje liczą Z=gx⋅yZ=g^{x\cdot y}. Przeciwnik pośrodku może zastąpić punkty i uzgodnić dwa sekrety. Zgodność uczciwego rachunku nie zapewnia tożsamości rozmówcy.

Podstawowa wymiana Diffiego–Hellmana: algorytmy i przepływ

To jeszcze nie AKE. Nie ma klucza tożsamości ani uwierzytelnienia partnera. Start tworzy jednorazową parę sesji, a Finish kończy lokalne obliczenie.

Π=(Setup,Start,Finish)\Pi=(\mathsf{Setup},\mathsf{Start},\mathsf{Finish})
Setup(1λ)\mathsf{Setup}(1^\lambda)⟶pp\longrightarrow pp
pp=(G,q,g)pp=(G,q,g)
∣G∣=q,G=⟨g⟩|G|=q,\quad G=\langle g\rangle

Rząd q jest liczbą pierwszą. Ustal kodowania i działania grupy. Dodatkowe funkcje wskazano przy konstrukcji.

Start(pp)\mathsf{Start}(pp)⟶(X,st)\longrightarrow (X,st)
x←$Zq∗,X=gx,st=xx\overset{\$}{\leftarrow}\mathbb Z_q^*,\quad X=g^x,\quad st=x
Finish(pp,st,Y)\mathsf{Finish}(pp,st,Y)⟶Z\longrightarrow Z
Z=YxZ=Y^x

Sprawdź podgrupę i odrzuć neutralny Y. Wynik jest elementem grupy, nie kluczem AES.

Podstawowa wymiana Diffiego–Hellmana: czynności i komunikatyAlicjaBobStartPierwszy wkładStartDrugi wkładFinishFinish

Podstawowa wymiana Diffiego–Hellmana

Alicja: pppp

Bob: pppp

  1. Alicja, Start: x←$Zq∗,X=gxx\overset{\$}{\leftarrow}\mathbb Z_q^*,\quad X=g^x
  2. Alicja → Bob: XX Pierwszy wkład
  3. Bob, Start: y←$Zq∗,Y=gyy\overset{\$}{\leftarrow}\mathbb Z_q^*,\quad Y=g^y
  4. Bob → Alicja: YY Drugi wkład
  5. Alicja, Finish: ZA=YxZ_A=Y^x
  6. Bob, Finish: ZB=XyZ_B=X^y
Obie strony lokalnie otrzymują ten sam element grupy. Nie przesyłają go sobie. Równość sekretów przy uczciwym wykonaniu nie uwierzytelnia źródła komunikatów. KDF i uwierzytelnienie są następnymi składnikami.

AKE łączy uwierzytelnianie z ustanowieniem świeżego klucza. Potrzebne są jednoznaczne kodowania, role, identyfikatory, transkrypt i właściwa KDF. Oddzielne etykiety wyznaczają klucze aplikacyjne, klucze MAC i kierunki komunikacji.

Od elementu grupy do bajtów klucza

Wspólny ZZ jest elementem grupy, nie od razu kluczem AES. Najpierw obie strony kodują go w identyczny ciąg bajtów encode⁡(Z)\operatorname{encode}(Z). Następnie KDF korzysta z tego tajnego materiału i jawnego kontekstu. Wyprowadza osobne bajty dla każdego zastosowania, np. klucz MAC kmk_m i klucz szyfrowania kEk_E. Kontekst zawiera uzgodnione identyfikatory protokołu, sesji i ról.

km=KDF(encode⁡(Z),ctx,MAC),kE=KDF(encode⁡(Z),ctx,encryption).k_m=\mathsf{KDF}(\operatorname{encode}(Z),\mathrm{ctx},\text{MAC}),\qquad k_E=\mathsf{KDF}(\operatorname{encode}(Z),\mathrm{ctx},\text{encryption}).

To zapis interfejsu, nie specyfikacja konkretnej KDF. W HKDF etap Extract przetwarza materiał wejściowy z użyciem soli, a Expand wyprowadza klucze z informacją o kontekście i przeznaczeniu. Szczegółowy profil protokołu określa kodowanie, sól i długości. Ten praktyczny mechanizm odróżniamy od idealnej wyroczni wyprowadzającej klucz w dowodzie NAXOS. Nie zastępujemy jednej drugim bez osobnej analizy.

Dwie rozmowy zamiast jednej: man in the middle

Alicja wysyła X=gxX=g^x, ale Ewa zatrzymuje go i wysyła Bobowi U=guU=g^u. Bob odpowiada Y=gyY=g^y, a Ewa podmienia odpowiedź dla Alicji na V=gvV=g^v. Alicja liczy VxV^x, które Ewa oblicza jako XvX^v. Bob liczy UyU^y, które Ewa oblicza jako YuY^u. Ewa nie zna xx ani yy, ale zna oba klucze.

Problemem nie jest złamanie CDH. Ewa rozwiązuje dwa zadania, w których sama wybrała jeden wykładnik. Potrzebujemy uwierzytelnienia wkładów i połączenia ich z tożsamościami oraz rolami. Samo poprawne potęgowanie po obu stronach nie daje tego związku.

Zobacz oba sekrety pośrednika

W poniższym rachunku X=gxX=g^x i Y=gyY=g^y są uczciwymi wkładami. W wariancie ataku Ewa podstawia U=guU=g^u dla Boba oraz V=gvV=g^v dla Alicji. Indeks recv\mathrm{recv} oznacza element faktycznie otrzymany z sieci. Sprawdzamy osobno Vx=XvV^x=X^v i Uy=YuU^y=Y^u. Strona Ewy używa wyłącznie przechwyconych elementów oraz własnych skalarów. Nie otrzymuje xx ani yy. Realizacja na krzywej zapisuje te same równości jako x⋅V=v⋅Xx\cdot V=v\cdot X i y⋅U=u⋅Yy\cdot U=u\cdot Y.

Diffie–Hellman: jedna rozmowa czy dwie?

MCL WebAssembly, BLS12-381. Małe edytowalne sekrety służą wyłącznie nauce. Rysunek przedstawia tok obliczeń, nie wysyłanie sekretów. Nie jest to pełny AKE.

Sieć
Diffie–Hellman: jedna rozmowa czy dwie?1. Alicja i Bob
X=gx,Y=gyX=g^x,\quad Y=g^y
oczekuje
2. Przekazanie albo podmiana
Xrecv=X,Yrecv=YX_{\rm recv}=X,\quad Y_{\rm recv}=Y
oczekuje
3. Wspólne elementy grupy
KA=Yrecvx,KB=XrecvyK_A=Y_{\rm recv}^x,\quad K_B=X_{\rm recv}^y
oczekuje
4. Kontrola zgodności i wiedzy Ewy
Yx=XyY^x=X^y
oczekuje

Zapis i obliczenia. Wzory schematu są multiplikatywne. MCL realizuje je na krzywej. Generator gg odpowiada punktowi P2P_2. W grupach punktów iloczyn oznacza dodawanie, potęga oznacza mnożenie punktu przez skalar, a odwrotność oznacza punkt przeciwny. Nie potęgujemy współrzędnych. Ten rachunek nie używa pairingu.

Gotowe.

Obliczenia MCL na krzywej. Poniżej pokazujemy konkretne operacje biblioteki. Grupy punktów zapisujemy addytywnie.

  1. Alicja i Bob

    Oczekuje.

  2. Przekazanie albo podmiana

    Oczekuje.

  3. Wspólne elementy grupy

    Oczekuje.

  4. Kontrola zgodności i wiedzy Ewy

    Oczekuje.

Sprawdź: Najpierw sprawdź uczciwą rozmowę. Następnie włącz podmianę. Kto potrafi teraz policzyć każdy z dwóch elementów grupy?

To demonstracja nieuwierzytelnionego DH, nie implementacja SIGMA ani NAXOS. Uzyskany punkt wymaga jeszcze wyprowadzenia kluczy z kontekstem. Dodanie KDF samo nie uwierzytelnia podstawionych wkładów.

SIGMA: podpis i MAC mają różne zadania

Podpis wiąże wkłady DH. MAC pod kluczem wyprowadzonym z DH wiąże tożsamość z wymianą.

SIGMA: podstawowy przepływ: algorytmy i przepływ

To podstawowa struktura SIGMA, nie kompletny profil IKE. Parametry obejmują grupę, podpis, MAC i KDF. Start i Next mają interfejs maszyny AKE z W10. Poniżej rozpisujemy ich czynności. Tożsamości muszą odpowiadać zarejestrowanym kluczom. Początkowy stan Boba zawiera parametry, jego klucz sekretny, rolę i oczekiwanego partnera.

IKE
Internet Key Exchange. Protokół uzgadniania kluczy i parametrów ochrony połączenia.
Π=(Setup,KeyGen,Start,Next)\Pi=(\mathsf{Setup},\mathsf{KeyGen},\mathsf{Start},\mathsf{Next})
Setup(1λ)\mathsf{Setup}(1^\lambda)⟶pp\longrightarrow pp
pp=(ppDH,ppsig,KDF,Tag,Check)pp=(pp_{\mathrm{DH}},pp_{\mathrm{sig}},\mathsf{KDF},\mathsf{Tag},\mathsf{Check})

Ustal kodowania, role i kontekst pełnego profilu.

KeyGen(pp)\mathsf{KeyGen}(pp)⟶(pk,sk)\longrightarrow (pk,sk)
(pk,sk)←KeyGensig(ppsig)(pk,sk)\leftarrow\mathsf{KeyGen}_{\mathrm{sig}}(pp_{\mathrm{sig}})

Klucz podpisu wiążemy z tożsamością.

StartA(pp,skA,IDB)\mathsf{Start}_A(pp,sk_A,\mathrm{ID}_B)⟶(X,stA)\longrightarrow (X,st_A)
x←$Zq∗,X=gxx\overset{\$}{\leftarrow}\mathbb Z_q^*,\quad X=g^x

Zapamiętaj x, X, partnera i rolę.

NextB(stB,X)\mathsf{Next}_B(st_B,X)⟶(M2,stB′)\longrightarrow (M_2,st_B\prime)
y←$Zq∗,Y=gy,Z=Xyy\overset{\$}{\leftarrow}\mathbb Z_q^*,\quad Y=g^y,\quad Z=X^y
σB←Sign(ppsig,skB,enc⁡(X,Y))\sigma_B\leftarrow\mathsf{Sign}(pp_{\mathrm{sig}},sk_B,\operatorname{enc}(X,Y))
τB=Tag(km,enc⁡(IDB))\tau_B=\mathsf{Tag}(k_m,\operatorname{enc}(\mathrm{ID}_B))
M2=(Y,IDB,σB,τB)M_2=(Y,\mathrm{ID}_B,\sigma_B,\tau_B)

Wyprowadź k_m z Z i kontekstu. Zachowaj stan do kontroli M₃.

NextA(stA,M2)\mathsf{Next}_A(st_A,M_2)⟶(M3,stA′)\longrightarrow (M_3,st_A\prime)
Z=YxZ=Y^x
σA←Sign(ppsig,skA,enc⁡(Y,X))\sigma_A\leftarrow\mathsf{Sign}(pp_{\mathrm{sig}},sk_A,\operatorname{enc}(Y,X))
τA=Tag(km,enc⁡(IDA))\tau_A=\mathsf{Tag}(k_m,\operatorname{enc}(\mathrm{ID}_A))
M3=(IDA,σA,τA)M_3=(\mathrm{ID}_A,\sigma_A,\tau_A)

Najpierw waliduj Y, związek ID_B z kluczem, podpis i MAC. Przy błędzie odrzuć. Wyprowadź oddzielny klucz aplikacji.

NextB(stB′,M3)\mathsf{Next}_B(st_B\prime,M_3)⟶stB′′\longrightarrow st_B\prime\prime
Verify(ppsig,pkA,enc⁡(Y,X),σA)=1\mathsf{Verify}(pp_{\mathrm{sig}},pk_A,\operatorname{enc}(Y,X),\sigma_A)=1
Check(km,enc⁡(IDA),τA)=1\mathsf{Check}(k_m,\operatorname{enc}(\mathrm{ID}_A),\tau_A)=1

Sprawdź partnera. Stan accepted jest wydawany tylko po wymaganych kontrolach profilu.

SIGMA: podstawowy przepływ: czynności i komunikatyAlicjaBobStart: pierwszy wkład
Sekret x pozostaje u Alicji.
1. Wkład Diffiego–HellmanaNext: wkład i klucz MAC
Najpierw sprawdź grupę i niejednostkowość X.
Next: podpis i znacznik tożsamości2. Wkład, tożsamość, podpis i MAC BobaNext: odtwórz klucz MAC
Najpierw sprawdź grupę i niejednostkowość Y.
Next: sprawdź Boba
Sprawdź też powiązanie ID z kluczem partnera.
Next: własny podpis i MAC
Odpowiedz tylko po poprawnej weryfikacji.
3. Tożsamość, podpis i MAC AlicjiNext: sprawdź Alicję
Sprawdź też powiązanie ID z kluczem partnera.

SIGMA: podstawowy przepływ

Alicja: pp,skA,pkBpp,sk_A,pk_B

Bob: pp,skB,pkApp,sk_B,pk_A

  1. Alicja, Start: pierwszy wkład: x←$Zq∗,X=gxx\overset{\$}{\leftarrow}\mathbb Z_q^*,\quad X=g^x Sekret x pozostaje u Alicji.
  2. Alicja → Bob: XX 1. Wkład Diffiego–Hellmana
  3. Bob, Next: wkład i klucz MAC: y←$Zq∗,Y=gyy\overset{\$}{\leftarrow}\mathbb Z_q^*,\quad Y=g^y Z=XyZ=X^y km=KDF(enc⁡(Z),ctx,MAC)k_m=\mathsf{KDF}(\operatorname{enc}(Z),\mathrm{ctx},\mathtt{MAC}) Najpierw sprawdź grupę i niejednostkowość X.
  4. Bob, Next: podpis i znacznik tożsamości: mB=enc⁡(X,Y)m_B=\operatorname{enc}(X,Y) σB←Sign(skB,mB)\sigma_B\leftarrow\mathsf{Sign}(sk_B,m_B) τB=Tag(km,enc⁡(IDB))\tau_B=\mathsf{Tag}(k_m,\operatorname{enc}(\mathrm{ID}_B))
  5. Bob → Alicja: (Y,IDB,σB,τB)(Y,\mathrm{ID}_B,\sigma_B,\tau_B) 2. Wkład, tożsamość, podpis i MAC Boba
  6. Alicja, Next: odtwórz klucz MAC: Z=YxZ=Y^x km=KDF(enc⁡(Z),ctx,MAC)k_m=\mathsf{KDF}(\operatorname{enc}(Z),\mathrm{ctx},\mathtt{MAC}) Najpierw sprawdź grupę i niejednostkowość Y.
  7. Alicja, Next: sprawdź Boba: mB=enc⁡(X,Y)m_B=\operatorname{enc}(X,Y) Verify(pkB,mB,σB)=?1\mathsf{Verify}(pk_B,m_B,\sigma_B)\stackrel{?}{=}1 Check(km,enc⁡(IDB),τB)=?1\mathsf{Check}(k_m,\operatorname{enc}(\mathrm{ID}_B),\tau_B)\stackrel{?}{=}1 Sprawdź też powiązanie ID z kluczem partnera.
  8. Alicja, Next: własny podpis i MAC: mA=enc⁡(Y,X)m_A=\operatorname{enc}(Y,X) σA←Sign(skA,mA)\sigma_A\leftarrow\mathsf{Sign}(sk_A,m_A) τA=Tag(km,enc⁡(IDA))\tau_A=\mathsf{Tag}(k_m,\operatorname{enc}(\mathrm{ID}_A)) Odpowiedz tylko po poprawnej weryfikacji.
  9. Alicja → Bob: (IDA,σA,τA)(\mathrm{ID}_A,\sigma_A,\tau_A) 3. Tożsamość, podpis i MAC Alicji
  10. Bob, Next: sprawdź Alicję: mA=enc⁡(Y,X)m_A=\operatorname{enc}(Y,X) Verify(pkA,mA,σA)=?1\mathsf{Verify}(pk_A,m_A,\sigma_A)\stackrel{?}{=}1 Check(km,enc⁡(IDA),τA)=?1\mathsf{Check}(k_m,\operatorname{enc}(\mathrm{ID}_A),\tau_A)\stackrel{?}{=}1 Sprawdź też powiązanie ID z kluczem partnera.
W wywołaniach Sign i Verify pominięto wspólne parametry publiczne z tabeli. KDF używa tego samego kodowania i kontekstu po obu stronach. Klucz aplikacji wyprowadza się oddzielnie od klucza MAC i wydaje dopiero zgodnie z regułami akceptacji profilu. Błąd którejkolwiek kontroli przerywa sesję. Krawczyk, SIGMA, §5.1.
ID
identifier / identification. Identyfikator / identyfikacja, zależnie od nazwy pola. RP ID identyfikuje usługę, a ID Token przekazuje informację o uwierzytelnieniu.

To nie kompletny format IKE. Profile określają kontekst, role, kodowania i ewentualne szyfrowanie tożsamości. Klucz musi być powiązany ze sprawdzoną tożsamością. Podpis pod jednym punktem nie zastępuje konstrukcji.

Który algorytm jest wywoływany w SIGMA

Rozpiszmy skróty z rysunku. Parametry schematu podpisu oznaczamy przez ppsigpp_{\mathrm{sig}}, a zarejestrowane klucze Boba przez (pkB,skB)(pk_B,sk_B). Dla podstawowego przepływu powyżej mB=enc⁡(X,Y)m_B=\operatorname{enc}(X,Y) jest podpisywaną wiadomością Boba, a mA=enc⁡(Y,X)m_A=\operatorname{enc}(Y,X) wiadomością Alicji. Kolejność pól rozróżnia role. Pełny profil ustala ponadto separatory domen i kontekst protokołu.

  1. Bob oblicza wspólny sekret: Z=XyZ=X^y. Z jego kodowania wyprowadza klucz kmk_m do MAC i oddzielny materiał na klucz aplikacyjny.
  2. Bob wywołuje podpis: σB←Sign(ppsig,skB,mB)\sigma_B\leftarrow\mathsf{Sign}(pp_{\mathrm{sig}},sk_B,m_B). Klucz skBsk_B pozostaje w urządzeniu, a σB\sigma_B trafia do komunikatu.
  3. Bob uwierzytelnia tożsamość w tej wymianie: τB←Tag(km,enc⁡(IDB))\tau_B\leftarrow\mathsf{Tag}(k_m,\operatorname{enc}(\mathrm{ID}_B)). To znacznik MAC, nie drugi podpis cyfrowy.
  4. Alicja weryfikuje: oblicza Z=YxZ=Y^x i zgodny kmk_m. Uruchamia Verify(ppsig,pkB,mB,σB)\mathsf{Verify}(pp_{\mathrm{sig}},pk_B,m_B,\sigma_B) oraz Check(km,enc⁡(IDB),τB)\mathsf{Check}(k_m,\operatorname{enc}(\mathrm{ID}_B),\tau_B). Sprawdza również, czy pkBpk_B jest właściwym zarejestrowanym kluczem wskazanego partnera.
  5. Alicja odsyła własny dowód: wywołuje Sign ze swoim skAsk_A dla mAm_A oraz Tag dla swojej tożsamości. Bob wykonuje odpowiadające sprawdzenia. Każda lokalna sesja wydaje klucz aplikacji dopiero zgodnie z warunkami akceptacji profilu.

To rozwinięcie interfejsów Sign, Verify, Tag i Check w podstawowej strukturze SIGMA, nie kompletna specyfikacja IKE. Konkretne kodowania, certyfikaty, ochrona tożsamości i momenty akceptacji wymagają pełnego profilu. Porównanie ról podpisu i MAC oraz warianty przepływu przedstawia Krawczyk, SIGMA, §5.

NAXOS: zalążek nie jest wykładnikiem

Ten sam cel AKE, inne wnętrze algorytmu Next. NAXOS nie jest SIGMA z zamienionym haszem. Zamiast dołączać podpisy wiąże długoterminowe i efemeryczne sekrety poprzez działania grupowe oraz wyrocznie wyprowadzające wykładnik i klucz. Dlatego nie dopisujemy mu wywołania Sign, którego w tej konstrukcji nie ma.

NAXOS: dwie wiadomości, trzy wspólne składniki: algorytmy i przepływ

Publiczne A i B są zaufanymi kluczami partnerów. ℋ zwraca skalar, a niezależna wyrocznia 𝒦 klucz bitowy. Prywatne zalążki mają długość ustaloną w parametrach. Początkowy stan Boba zawiera jego sekret, parametry i tożsamości obu stron.

Π=(Setup,KeyGen,Start,Next)\Pi=(\mathsf{Setup},\mathsf{KeyGen},\mathsf{Start},\mathsf{Next})
Setup(1λ)\mathsf{Setup}(1^\lambda)⟶pp\longrightarrow pp
pp=(G,q,g,ℓ,ℋ,K)pp=(G,q,g,\ell,\mathcal H,\mathcal K)
KeyGen(pp)\mathsf{KeyGen}(pp)⟶(A,a)\longrightarrow (A,a)
a←$Zq∗,A=gaa\overset{\$}{\leftarrow}\mathbb Z_q^*,\quad A=g^a

Sekret a pozostaje u właściciela. Odbiorca uwierzytelnia publiczny A.

Start(pp,a,IDB)\mathsf{Start}(pp,a,\mathrm{ID}_B)⟶(X,stA)\longrightarrow (X,st_A)
rA←${0,1}ℓr_A\overset{\$}{\leftarrow}\{0,1\}^{\ell}
x=ℋ(enc⁡(rA,a)),X=gxx=\mathcal H(\operatorname{enc}(r_A,a)),\quad X=g^x

Stan obejmuje zalążek, rolę, partnera i dane potrzebne do końcowego obliczenia.

NextA(stA,Y,B)\mathsf{Next}_A(st_A,Y,B)⟶KA\longrightarrow K_A
KA=K(Ya,Bx,Yx,IDA,IDB)K_A=\mathcal K(Y^a,B^x,Y^x,\mathrm{ID}_A,\mathrm{ID}_B)

Po kontroli punktu Y i zaufanego klucza B.

NextB(stB,X,A)\mathsf{Next}_B(st_B,X,A)⟶(Y,KB)\longrightarrow (Y,K_B)
rB←${0,1}ℓr_B\overset{\$}{\leftarrow}\{0,1\}^{\ell}
y=ℋ(enc⁡(rB,b)),Y=gyy=\mathcal H(\operatorname{enc}(r_B,b)),\quad Y=g^y
KB=K(Ay,Xb,Xy,IDA,IDB)K_B=\mathcal K(A^y,X^b,X^y,\mathrm{ID}_A,\mathrm{ID}_B)

Ten sam porządek tożsamości i składników. Nie dodajemy nieobecnego w NAXOS podpisu.

NAXOS: dwie wiadomości, trzy wspólne składniki: czynności i komunikatyAlicjaBobStartWkład z pochodnego wykładnikaNextDrugi wkładNext: wyprowadzenie kluczaNext: wyprowadzenie klucza

NAXOS: dwie wiadomości, trzy wspólne składniki

Alicja: pp,a,Bpp,a,B

Bob: pp,b,App,b,A

  1. Alicja, Start: rA←${0,1}ℓr_A\overset{\$}{\leftarrow}\{0,1\}^{\ell} x=ℋ(enc⁡(rA,a))x=\mathcal H(\operatorname{enc}(r_A,a)) X=gxX=g^x
  2. Alicja → Bob: XX Wkład z pochodnego wykładnika
  3. Bob, Next: rB←${0,1}ℓr_B\overset{\$}{\leftarrow}\{0,1\}^{\ell} y=ℋ(enc⁡(rB,b))y=\mathcal H(\operatorname{enc}(r_B,b)) Y=gyY=g^y
  4. Bob → Alicja: YY Drugi wkład
  5. Alicja, Next: wyprowadzenie klucza: KA=K(Ya,Bx,Yx,IDA,IDB)K_A=\mathcal K(Y^a,B^x,Y^x,\mathrm{ID}_A,\mathrm{ID}_B)
  6. Bob, Next: wyprowadzenie klucza: KB=K(Ay,Xb,Xy,IDA,IDB)K_B=\mathcal K(A^y,X^b,X^y,\mathrm{ID}_A,\mathrm{ID}_B)
Wspólne składniki mają tę samą kolejność. Ujawnienie zalążka nie jest tym samym co ujawnienie pochodnego wykładnika. Model świeżości jest opisany w części dowodowej.

Alicja ma sekret stały aa i zalążek rAr_A, Bob b,rBb,r_B. Niech A=gaA=g^a, B=gbB=g^b:

x=ℋ(enc⁡(rA,a)),y=ℋ(enc⁡(rB,b)),X=gx,Y=gy.x=\mathcal H(\operatorname{enc}(r_A,a)),\quad y=\mathcal H(\operatorname{enc}(r_B,b)),\quad X=g^x,\quad Y=g^y.

ℋ\mathcal H oznacza tutaj skalarną wyrocznię H1H_1 publikacji. Niezależna K\mathcal K odpowiada wyroczni klucza H2H_2 i daje ciąg bitów:

KA=K(Ya,Bx,Yx,IDA,IDB),KB=K(Ay,Xb,Xy,IDA,IDB).\begin{aligned} K_A&=\mathcal K(Y^a,B^x,Y^x,\mathrm{ID}_A,\mathrm{ID}_B),\\ K_B&=\mathcal K(A^y,X^b,X^y,\mathrm{ID}_A,\mathrm{ID}_B). \end{aligned}

Składniki są kolejno równe ga⋅yg^{a\cdot y}, gb⋅xg^{b\cdot x} i gx⋅yg^{x\cdot y}. Tożsamości mają ten sam porządek. Ujawnienie rAr_A nie jest ujawnieniem xx. Bez aa nie odtwarza się po prostu wejścia hasza.

Co wykazujemy poza poprawnością

  1. Określamy sesję, partnerowanie, zakończenie i ujawniane stany.
  2. Wybieramy świeżą sesję testową. Nie ujawniamy jej klucza ani klucza partnera.
  3. Definiujemy kompromitacje. CK i eCK nie są jedną definicją.
    CK
    Canetti–Krawczyk. Nazwiska autorów modelu bezpieczeństwa uwierzytelnionej wymiany klucza.
    eCK
    extended Canetti–Krawczyk. Rozszerzony model Canettiego–Krawczyka. Dopuszczalne ujawnienia określa jego definicja.
  4. Symulujemy wszystkie dozwolone zapytania, a udane rozróżnianie przekształcamy w rozwiązanie problemu trudnego.

Pogłębienie AKE zawiera gry i przypadki ujawnień. L5 rozdziela obliczenia DH i KDF od uwierzytelniania.

Od klucza sesji do kanału

Klucz AKE jest wynikiem protokołu, nie gotowym szyfrogramem. Po akceptacji wyprowadzamy oddzielne klucze kierunkowe. Dla jednego kierunku używamy poznanego AEAD:

C←EncAEAD(kA→B,n,m,d),m′←DecAEAD(kA→B,n,C,d).C\leftarrow\mathsf{Enc}_{\mathrm{AEAD}}(k_{A\to B},n,m,d),\qquad m'\leftarrow\mathsf{Dec}_{\mathrm{AEAD}}(k_{A\to B},n,C,d).

Tutaj nn jest nonce unikalnym dla danego klucza w profilu wymagającym unikalności, a dd jawnymi danymi dodatkowymi. Mogą one wiązać identyfikator sesji, kierunek i numer rekordu. Odbiorca przekazuje m′m' aplikacji tylko po poprawnej kontroli. Musi również egzekwować politykę numerów rekordów, bo sam poprawny tag nie wykrywa ponownego dostarczenia całego starego rekordu.

Widzimy już trzy różne warstwy: podpis uwierzytelnia dane wymiany, AKE ustanawia klucze, AEAD chroni rekordy. Następny rozdział rozwiąże inny problem: zaszyfrowanie wiadomości, kiedy odbiorca nie uczestniczy teraz w rozmowie.

Źródła: Krawczyk, SIGMA, LaMacchia–Lauter–Mityagin, NAXOS.