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

Kryptografia II stopień

Python, notebooki Jupyter i py_ecc. Od rachunku modularnego do protokołów na krzywych eliptycznych.

Od równania do testu

Laboratorium prowadzi od ochrony danych do identyfikacji, podpisu i ustalania klucza. W każdym eksperymencie porównujemy poprawny przebieg z kontrolowaną zmianą. Zmiana może dotyczyć danych, reguły algorytmu albo możliwości przeciwnika.

Bank zadań do wyboru. Prowadzący laboratorium wybiera zadania odpowiednio do przygotowania grupy. Podaje ich liczbę, zakres, terminy oraz zasady zaliczenia zgodne z kartą przedmiotu. Nie ma obowiązku wykonania wszystkich zamieszczonych propozycji. Oznaczenia list służą nawigacji, nie wyznaczają kolejnych tygodni zajęć.

Proponowany początek: L0a, ciała skończone i krzywe. Własna arytmetyka pomaga zrozumieć operacje wykonywane później przez bibliotekę. Następnie można wykorzystać ją w GHASH, podpisie Schnorra i uzgadnianiu klucza DH. Prowadzący wybiera również warianty algebraiczne. Nie trzeba implementować każdego schematu we wszystkich grupach.

DH
Diffie–Hellman. Nazwiska autorów metody uzgadniania wspólnego sekretu.

Zaczynamy od Pythona i notebooków Jupyter. W jednym pliku zapisujemy równania, kod, wyniki i wnioski. Najpierw sprawdzamy mechanizm na małych liczbach, następnie na krzywej eliptycznej. Do własnych eksperymentów można też wykorzystać MCL i wrappery studenckie, które udostępniają operacje tej biblioteki w innych językach. Python pozostaje podstawową ścieżką laboratoriów. MCL jest szczególnie przydatny, gdy poprawnie działający schemat chcemy uruchamiać wielokrotnie i mierzyć jego wydajność.

MCL
mcl. Nazwa biblioteki kryptograficznej Herumi do szybkich obliczeń grupowych i pairingów.
Narzędzie Zastosowanie
gmpy2 Liczby całkowite, potęgowanie modularne i odwrotność. Rozgrzewka z grupą modulo liczby pierwszej.
py_ecc Punkty BLS12-381 w G1G_1 i G2G_2, skalary i pairingi. Własne dydaktyczne implementacje protokołów.
cryptography Gotowe implementacje AES-GCM, RSA-OAEP, RSA-PSS, HKDF i ECDSA.
JupyterLab Notebook jako wykonywalny raport z zachowanymi wynikami.
MCL i wrappery Opcjonalne rozszerzenie: szybkie operacje grupowe, serie testów i porównania wydajności.
py_ecc
Elliptic Curve Cryptography. Kryptografia na krzywych eliptycznych. py_ecc jest nazwą omawianej biblioteki Pythona.
BLS12-381
Barreto–Lynn–Scott. Rodzina krzywych eliptycznych. W BLS12-381 stopień zanurzenia wynosi 12, a moduł ciała bazowego ma 381 bitów. To inny zestaw nazwisk niż w podpisie BLS.
AES-GCM
Advanced Encryption Standard in Galois/Counter Mode. Szyfr AES w trybie Galois/licznikowym. AESGCM jest nazwą klasy w bibliotece, a 256 oznacza długość klucza.
RSA-OAEP
RSA Encryption Scheme with Optimal Asymmetric Encryption Padding. Schemat szyfrowania RSA z kodowaniem OAEP.
RSA-PSS
RSA Signature Scheme with Appendix, with Probabilistic Signature Scheme encoding. Podpis RSA z kodowaniem PSS. Wiadomość towarzyszy podpisowi, a nie jest z niego odzyskiwana.
HKDF
HMAC-based Extract-and-Expand Key Derivation Function. Funkcja wyprowadzania kluczy oparta na HMAC, z etapami ekstrakcji i rozszerzania.
ECDSA
Elliptic Curve Digital Signature Algorithm. Algorytm podpisu cyfrowego na krzywych eliptycznych.

py_ecc nie jest biblioteką do AES ani RSA. Z kolei gmpy2 udostępnia arytmetykę, a nie gotowy bezpieczny protokół. Kod laboratoriów jest dydaktyczny. Autorzy py_ecc oznaczają bibliotekę jako eksperymentalną i nieaudytowaną. Nie zakładamy stałego czasu wykonania ani odporności naszych programów na kanały boczne. Używamy wyłącznie danych testowych.

AES
Advanced Encryption Standard. Standard szyfrowania blokowego. Liczby 128, 192 i 256 oznaczają długości klucza w bitach.
RSA
Rivest–Shamir–Adleman. Nazwiska autorów kryptosystemu z kluczem publicznym.

Notebook na początek

Notebook: Schnorr, grupy i notacja · Pakiety do instalacji

Notebook zawiera mały rachunek modulo, identyfikację i podpis Schnorra w obu grupach krzywej, przykład przeciążenia operatorów oraz testy. To punkt wyjścia do własnych implementacji i rozszerzeń z L2–L4, nie rozwiązanie wszystkich laboratoriów. Pobierz oba pliki do jednego katalogu. Utwórz osobne środowisko z Pythonem 3.10 lub nowszym:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r kryptografia-ii-python-requirements.txt
python -m jupyterlab kryptografia-ii-python.ipynb

W Windows środowisko w PowerShell aktywuje polecenie .venv\Scripts\Activate.ps1. Po zmianach uruchom notebook od początku w świeżym kernelu. Raport nie może zależeć od niewidocznych obliczeń wykonanych wcześniej w innej kolejności.

Na początek przeczytaj podstawy zapisu, schemat jako krotkę algorytmów, a następnie model przeciwnika i wyrocznie. L0 i zadania 1–5 z L1 nie wymagają znajomości protokołów grupowych. Zadania algebraiczne z L1 korzystają z L0a. Po W6–W7 wykonaj rozgrzewkę i poprawną identyfikację z L3. Następnie wróć do ataków w L2 i przejdź do podpisów w L4.

Raport: dla każdego zadania zapisz wejścia publiczne, badany wariant, polecenie lub fragment kodu, wynik, test negatywny i wniosek. Podaj wersję biblioteki lub sumę kontrolną pliku oraz środowisko wykonania. Klucze testowe można pokazać w zamkniętym raporcie. Nigdy nie używaj rzeczywistych kluczy, haseł ani prywatnych danych.

Każdy test powinien mieć jednoznaczne oczekiwanie. „Program nie zgłosił błędu” nie jest wystarczającym testem weryfikacji.

Interfejs przed implementacją

Zanim zaczniesz rachunek, zapisz krotkę algorytmów badanego schematu i przypisz im funkcje w notebooku. Dla każdej funkcji podaj argumenty, typ wyniku, dostęp do sekretów i ewentualny stan. Dopiero w tych funkcjach umieść działania biblioteki. Zmienna istniejąca w pamięci notebooka nie jest automatycznie dozwolonym wejściem każdego uczestnika.

  • Uczciwy przebieg: przygotuj parametry i klucze, uruchom Sign, a jego wynik przekaż wraz z wiadomością i kluczem publicznym do Verify. Dla szyfrowania analogicznie połącz Enc z Dec i porównaj odzyskane bajty z wejściem.
  • Oddzielne role: Verify nie może odczytywać sekretu ani nonce z globalnej zmiennej. W MAC sytuacja jest inna, ponieważ jego sprawdzanie wymaga wspólnego tajnego klucza. Nie przenoś tego samego interfejsu między tymi funkcjonalnościami.
    MAC
    Message Authentication Code. Kod uwierzytelnienia wiadomości, sprawdzany przy użyciu klucza.
  • Przeciwnik: umieść strategię ataku w osobnej funkcji. Udostępnij tylko publiczne dane i dozwolone usługi. Usługa podpisująca może wewnętrznie znać sekret, ale funkcja przeciwnika otrzymuje wyłącznie odpowiedzi na zapytania.
  • Wynik eksperymentu: odróżnij akceptację przez Verify od nowego fałszerstwa. Do drugiego testu potrzebujesz także zbioru wcześniej podpisywanych wiadomości oraz ustalonego atakowanego klucza.

Podział funkcji w notebooku nie tworzy technicznej izolacji pamięci. Służy kontroli modelu i wymaga przeglądu kodu. Test poprawności, test konkretnego ataku i dowód bezpieczeństwa to trzy różne wyniki pracy. Nie nazywaj serii nieudanych prób dowodem niepodrabialności. Te zasady stosuj do każdej listy, także wtedy, gdy obliczenia wykonuje gotowa biblioteka.

Demonstratory na stronie pozostają narzędziem porównawczym. Kod JavaScript wykorzystuje MCL WebAssembly i WebCrypto. Nie trzeba przenosić tych bibliotek do notebooka. Przy uruchamianiu lokalnej kopii strony użyj serwera HTTP na localhost, a na serwerze publicznym HTTPS. Weryfikacja podpisu otrzymuje wyłącznie publiczne dane określone w jej interfejsie. Weryfikacja MAC wymaga natomiast właściwego wspólnego sekretu. Język implementacji nie zmienia tych ról.

WebAssembly
WebAssembly. Format kodu wykonywanego m.in. w przeglądarce. Wasm i WASM to jego skrócone nazwy.
HTTP
Hypertext Transfer Protocol. Protokół wymiany żądań i odpowiedzi w sieci WWW.
HTTPS
Hypertext Transfer Protocol Secure. HTTP przesyłany przez połączenie chronione protokołem TLS.

L0a. Ciała skończone, krzywe i kodowanie

Przygotowanie: C0a, rachunek przed implementacją oraz warsztat W6: odwrotność, wielomiany, działania na punktach, potęgowanie i kodowanie. Celem jest własna, testowalna warstwa arytmetyczna. Gotowej biblioteki używaj do porównania wyników, nie zamiast implementacji wskazanych operacji. Rozszerzenia i krzywe binarne mogą być osobnymi wariantami dla zainteresowanych.

Dwa różne obiekty. Ciało Fpk\mathbb F_{p^k} ma pkp^k elementów. Gdy k>1k>1, nie jest pierścieniem liczb całkowitych modulo pkp^k. Współrzędne krzywej należą do ciała, natomiast skalary protokołu liczymy modulo rząd wybranej podgrupy. Oznaczamy go przez qq.

  1. Arytmetyka w Fp\mathbb F_p. Dla pierwszej liczby pp zaimplementuj dodawanie, odejmowanie, negację, mnożenie, odwrotność, dzielenie i szybkie potęgowanie. Używaj liczb całkowitych dowolnej precyzji. Odwrotność policz rozszerzonym algorytmem Euklidesa. Potęgowanie dla dodatniego wykładnika nn ma wykonywać O(log⁡n)O(\log n) mnożeń. Osobno obsłuż n=0n=0 i wyklucz odwracanie zera. Dla każdego niezerowego aa ma zachodzić a⋅a−1=1a\cdot a^{-1}=1. Parametr pp ma pochodzić ze sprawdzonego zestawu albo przejść jawnie wskazany test pierwszości. Po małych przykładach sprawdź działanie na liczbach 256- i 512-bitowych. To test obsługi dużych liczb, nie deklaracja poziomu bezpieczeństwa.
  2. Rozszerzenie Fpk\mathbb F_{p^k}. Zaimplementuj element jako wielomian stopnia mniejszego niż kk o współczynnikach w Fp\mathbb F_p. Działania wykonuj modulo ustalony moniczny, nierozkładalny wielomian f(t)f(t) stopnia kk. Zapisz parametry razem z elementem i odrzucaj mieszanie różnych ciał. Zaimplementuj redukcję wielomianową oraz odwrotność przez rozszerzony algorytm Euklidesa dla wielomianów. Dla F25=F5[t]/(t2+2)\mathbb F_{25}=\mathbb F_5[t]/(t^2+2) sprawdź wszystkie niezerowe elementy. Oznaczając klasę tt przez α\alpha, otrzymujesz α2=3\alpha^2=3 i α−1=2⋅α\alpha^{-1}=2\cdot\alpha. Wskaż, jak sprawdzono nierozkładalność użytego ff. Generator nierozkładalnych wielomianów jest opcjonalnym rozszerzeniem.
  3. Wariant binarny. Przyspiesz działania w F2k\mathbb F_{2^k}, reprezentując współczynnik przy tit^i bitem o numerze ii, liczonym od najmniej znaczącego bitu liczby całkowitej. Dodawanie jest XOR-em. Mnożenie wymaga redukcji wielomianowej, a nie redukcji całkowitoliczbowej modulo 2k2^k. Sprawdź F16\mathbb F_{16} z f=t4+t+1f=t^4+t+1, następnie F256\mathbb F_{256} z wielomianem AES f=t8+t4+t3+t+1f=t^8+t^4+t^3+t+1. Kontrole w zapisie szesnastkowym: 57 · 83 = c1 oraz 53 · ca = 01. Zapisz konwersję między bajtem a wielomianem. Konwencji tej nie przenoś bezpośrednio do GHASH z L1.6.
    XOR
    exclusive OR. Alternatywa wykluczająca. Wynik to 1 dokładnie wtedy, gdy dwa bity są różne.
  4. Krzywa nad ciałem o charakterystyce większej niż 3. Dla E:y2=x3+a⋅x+bE:y^2=x^3+a\cdot x+b sprawdź warunek 4⋅a3+27⋅b2≠04\cdot a^3+27\cdot b^2\ne0. Zaimplementuj punkt neutralny O\mathcal O, negację, dodawanie, podwajanie i mnożenie punktu przez skalar. Osobno obsłuż P+OP+\mathcal O, P+(−P)P+(-P) i podwajanie przy y=0y=0. Na małej krzywej nad F17\mathbb F_{17} z a=b=2a=b=2 sprawdź P=(5,1)P=(5,1), 2⋅P=(6,3)2\cdot P=(6,3) i 19⋅P=O19\cdot P=\mathcal O. Wylicz wszystkie punkty, sprawdź zamkniętość i łączność dla wszystkich trójek. Test skończonej krzywej nie zastępuje ogólnego dowodu prawa grupowego. Dopiero potem porównaj wybraną większą krzywą z biblioteką odniesienia.
  5. Pogłębienie: krzywa binarna. Zaimplementuj osobny typ dla E:y2+x⋅y=x3+a⋅x2+bE:y^2+x\cdot y=x^3+a\cdot x^2+b nad F2k\mathbb F_{2^k}, z b≠0b\ne0. Skorzystaj z odrębnych wzorów w SEC 1, §2.2.2. Nie podstawiaj charakterystyki 2 do wzorów z poprzedniego zadania. Negacja ma postać −(x,y)=(x,x+y)-(x,y)=(x,x+y). Na F16\mathbb F_{16} z zadania 3 przyjmij a=b=1a=b=1 i sprawdź, że P=(0,1)P=(0,1) należy do krzywej, a 2⋅P=O2\cdot P=\mathcal O. Przetestuj przypadki wyjątkowe oraz neutralność O\mathcal O. Tak mały przykład nie jest propozycją parametrów kryptograficznych.
  6. Wspólny format, niezależne programy. W parze uzgodnijcie zapis parametrów, elementów ciał i punktów, a następnie niezależnie napiszcie kodowanie i odczyt. Ustalcie kolejność współczynników, kolejność bajtów, stałe szerokości pól oraz oznaczenie O\mathcal O. Szesnastkowy tekst jest tylko zapisem bajtów. Nie określa sam konwencji wielomianowej. Przetestujcie zera wiodące, wartości brzegowe, niepoprawne długości i punkt spoza krzywej. Odrzucajcie niekanoniczne wartości współrzędnych zamiast redukować je po cichu modulo pp. Po wymianie plików porównajcie bajty oraz wyniki działań. W protokołach dołóżcie kontrolę podgrupy i zakaz neutralnego klucza zgodnie z ich profilem.

Wynik pracy: notebook lub moduł z testami, opis reprezentacji i wspólny zestaw wektorów wejście–wynik. W raporcie odróżnij błąd arytmetyki od błędu kodowania. Obsługa jednego ciała i jednej krzywej może stanowić samodzielny zakres uzgodniony z prowadzącym.

Źródła: zadania adaptują zakres listy 2 Marcina Słowika. Wzory i konwersje opisują SEC 1, §2.1–2.3 oraz notatki Bena Lynna. Dalsze zastosowania w L1.6–7, L4.6–7, L5.6–7 i L9.6 rozwijają wybrane zagadnienia z listy 3 Marcina Słowika.

L0. Pamięć eksperymentu i runda szyfru

Przygotowanie: model i wyrocznie, AES.

Zapytanie nie jest dostępem do sekretu

  1. Wyślij dokument:1 do wyroczni losowej. Zapisz wejście, odpowiedź, liczbę pytań oraz liczbę wierszy tabeli.
  2. Powtórz identyczne zapytanie. Odpowiedź musi pozostać ta sama, liczba pytań wzrasta, liczba wpisów nie.
  3. Zmień jeden znak wejścia. Sprawdź, że powstaje nowy wpis. Wynik może przypadkowo być równy poprzedniemu, ponieważ losujemy ze zbioru 101 skalarów. Takiej kolizji nie traktuj jako awarii.
  4. Przetestuj pusty ciąg oraz tekst ze spacją na końcu. Zapisuj dokładne bajty UTF-8. Nowy eksperyment usuwa całą tabelę, a nie pojedyncze zapytanie.
    UTF-8
    Unicode Transformation Format, 8-bit. Kodowanie znaków Unicode za pomocą jednostek 8-bitowych. Jeden znak może wymagać kilku bajtów.
  5. Wyjaśnij, dlaczego tabela jest stanem funkcji losowej, a nie zbiorem podpisów. Zaprojektuj osobny interfejs podpisywania. Wskaż, gdzie znajdowałby się jego klucz i co otrzymywałby pytający.
Wyrocznia losowa · sprawdzenie, losowanie, zapis

Model z małą dziedziną Z101\mathbb Z_{101}. Tabela jest początkowo pusta. Różne wejścia mogą otrzymać równy wynik.

Prywatna pamięć modelu wyroczniPrzeciwnik
A\mathcal A
zapytania i wynikiCzy wpis istnieje?
x∈dom⁡(T)?x\in\operatorname{dom}(T)?
TAK · odczytaj wpis
y←T[x]y\leftarrow T[x]
NIE · losuj niezależny wynik
y←$Z101y\overset{\$}{\leftarrow}\mathbb Z_{101}
Zapisz raz w tabeli
T[x]←yT[x]\leftarrow y
Zwróć tylko odpowiedź
ℋ(x)=y\mathcal H(x)=y
xx
yy
  1. Sprawdzenie
  2. Losowanie
  3. Zapis
  4. Odczyt
  5. Odpowiedź

Tabela jest pusta. Żadne zapytanie nie zostało wysłane.

Roboczy stan wewnętrznyBrak.

Prywatna tabela modelu

Podgląd dydaktyczny. Uczestnicy nie mogą odczytać tej pamięci bezpośrednio.

xxyy

Widok przeciwnika

Historia dostarczonych odpowiedzi. Wewnętrzne losowanie i tworzenie wpisu nie są osobnymi komunikatami.

ZapytanieOdpowiedź

Wniosek: wszystkie strony pytające tę samą wyrocznię korzystają z jednej spójnej funkcji. Mała przestrzeń wyników jest tylko ułatwieniem obserwacji. W dowodzie konkretnej konstrukcji zakres odpowiedzi musi odpowiadać jej parametrom.

Prześledź AES, zanim użyjesz trybu pracy

W demonstratorze AES wykonaj po kolei SubBytes, ShiftRows, MixColumns i AddRoundKey pierwszej rundy. Porównaj stany z przykładem NIST.

NIST
National Institute of Standards and Technology. Amerykański Narodowy Instytut Standaryzacji i Technologii.
  1. Zapisz 16 bajtów przed i po każdej operacji. Sprawdź, czy odczytujesz macierz kolumnami.
  2. Włącz różnicę jednego bitu wejścia przy tym samym kluczu. Policz różne bajty oraz różne bity. Wyjaśnij, dlaczego są to inne wielkości.
  3. Sprawdź niezmienność liczby różnych bitów po ShiftRows i AddRoundKey. Wskazuj konkretne stany, nie tylko obrazek.
  4. Przejdź do ostatniej rundy. Potwierdź brak MixColumns. Sprawdź szyfrogram końcowy 3ad77bb40d7a3660a89ecaf32466ef97.
  5. Wyłącz różnicę wejścia. Wszystkie odpowiadające sobie stany muszą być identyczne. Błąd długości wejścia powinien unieważnić wynik, zamiast zostawiać poprzedni jako aktualny.

Kod przebiegów: AES i pamięć wyroczni. To narzędzie obserwacji, nie biblioteka do ochrony danych. Tabelę wyroczni odtwórz w Pythonie jako słownik bajtów wejścia i wylosowanych odpowiedzi. W L1 korzystamy z gotowej implementacji AES-GCM w cryptography.

L1. Ochrona danych i AEAD

AEAD
Authenticated Encryption with Associated Data. Uwierzytelnione szyfrowanie z danymi dodatkowymi.

Przygotowanie: W3: OTP i strumień, W4: AES i AEAD, W5: hasze i MAC. Cel: odróżnić poufność od integralności i prawidłowo obsłużyć odrzucenie.

OTP
one-time pad. Szyfr z jednorazowym, losowym kluczem długości wiadomości.

W notebooku użyj klasy AESGCM z cryptography.hazmat.primitives.ciphers.aead. Klucz generuj przez AESGCM.generate_key(bit_length=256), nonce przez secrets.token_bytes(12). Odrzucenie uwierzytelnienia sygnalizuje wyjątek InvalidTag. Nie implementuj produkcyjnego AES ręcznie.

  1. Wygeneruj klucz AES-GCM długości 256 bitów oraz nonce długości 96 bitów przy użyciu kryptograficznego źródła losowości. Zaszyfruj krótki tekst UTF-8. Jako AAD podaj identyfikator i wersję dokumentu.
    AAD
    Additional Authenticated Data. Dodatkowe dane uwierzytelniane, ale nieszyfrowane.
  2. Odszyfruj szyfrogram z tym samym AAD. Sprawdź równość bajtów, nie tylko podobieństwo tekstu.
  3. Zmień osobno po jednym bicie szyfrogramu, AAD i nonce, zachowując pierwotny znacznik. Oczekiwaniem dla tych testów jest odrzucenie. Zapisz rzeczywisty wynik, zamiast ustawiać go w kodzie. Nie pokazuj częściowo odszyfrowanego tekstu jako poprawnego. Własność bezpieczeństwa ogranicza prawdopodobieństwo fałszerstwa. Nie oznacza bezwarunkowego wykrycia każdej możliwej zmiany przez znacznik skończonej długości.
  4. Powtórz eksperyment dla pustej wiadomości, polskich znaków oraz zmienionej długości danych. AAD jest uwierzytelniany, ale nie jest szyfrowany.
  5. Zaprojektuj format pakietu obejmujący wersję, identyfikator klucza, nonce i szyfrogram ze znacznikiem. Zapisz regułę unikalności nonce pod tym samym kluczem. Przypadkowo niepowtórzone nonce w kilku testach nie uzasadniają całego systemu.
AES-GCM · szyfrowanie i testy odrzucenia

WebCrypto, klucz 256-bitowy, nonce 96-bitowy, znacznik 128-bitowy. Każde wykonanie tworzy nowy klucz testowy.

Gotowe do rozpoczęcia.

Oczekiwane wyniki: poprawne wejście odtwarza tekst. Modyfikacje prowadzą do odrzucenia. Długość szyfrogramu obejmuje również znacznik. Interfejs WebCrypto nie przesyła klucza na serwer.

Pogłębienie: wykonaj serię pomiarów dla kilku rozmiarów bufora. Oddziel generowanie klucza od szyfrowania. Podaj liczbę powtórzeń, medianę i zakres pomiaru. Nie interpretuj czasu jednego wywołania jako miarodajnego benchmarku.

Źródła: WebCrypto, NIST SP 800-38D, interfejs AEAD.

SP
Special Publication. Seria publikacji specjalnych NIST.

Własna arytmetyka w szyfrze i uwierzytelnianiu

Przygotowanie: L0a.3, C2.5 i C4.6. Wykład wyjaśnia osobno mnożenie bajtów AES oraz kolejność bitów, bloki i maskę znacznika GCM. Są to dwa niezależne zadania do wyboru.

GCM
Galois/Counter Mode. Tryb Galois/licznikowy, łączący szyfrowanie ze sprawdzaniem integralności.
  1. GHASH, od mnożenia do znacznika GCM. Zaimplementuj mnożenie w F2128\mathbb F_{2^{128}} z wielomianem t128+t7+t2+t+1t^{128}+t^7+t^2+t+1. Przyjmij dokładnie kolejność bitów z NIST SP 800-38D, §6.3–6.4. Lewy bit bloku odpowiada współczynnikowi przy t0t^0. Element jednostkowy koduje więc blok 80 i 15 bajtów 00, a nie blok zakończony 01. Dla pełnych bloków S1,…,SnS_1,\ldots,S_n policz Y0=0Y_0=0, Yi=(Yi−1⊕Si)⋅HY_i=(Y_{i-1}\oplus S_i)\cdot H. Wynik YnY_n to GHASH⁡H(S)\operatorname{GHASH}_H(S). Osobno przygotuj wejście GCM: dopełnione zerami AAD, dopełniony szyfrogram i blok ich dwóch długości w bitach. Każda długość zajmuje 64 bity w kolejności big-endian. Nie dodawaj całego bloku dopełnienia, gdy dane już są wyrównane. Sprawdź puste dane, 1, 15, 16 i 17 bajtów. Dla 96-bitowego nonce NN oraz pełnego znacznika odtwórz H=AES⁡K(0128)H=\operatorname{AES}_K(0^{128}) i T=AES⁡K(N∥031∥1)⊕YnT=\operatorname{AES}_K(N\|0^{31}\|1)\oplus Y_n. AES weź z biblioteki, a wynik porównaj z AES-GCM tej samej biblioteki. Sam GHASH nie jest ani pełnym znacznikiem GCM, ani funkcją haszującą do krzywej.
  2. MixColumns na własnym ciele. Na bazie L0a.3 zaimplementuj xtime, czyli mnożenie przez wielomian tt, oraz mnożenie kolumny stanu przez macierz MixColumns z FIPS 197, §4.2 i §5.1.3. Wszystkie działania wykonuj w F256\mathbb F_{256} z wielomianem AES. Nie jest to mnożenie liczb rzeczywistych ani GHASH. Porównaj wynik z demonstratorem AES i wykonaj kontrolę kolumny d4 bf 5d 30 → 04 66 81 e5. Następnie zastosuj InvMixColumns i odzyskaj wejście. W raporcie pokaż jedną kolumnę z rozpisanymi działaniami. To implementacja operacji rundy, nie całego AES-GCM.
    FIPS
    Federal Information Processing Standards. Amerykańskie federalne standardy przetwarzania informacji.

Wynik pracy: kod arytmetyki, testy konwersji bitów i porównanie z niezależnym wynikiem. W przypadku GHASH pokaż osobno bloki wejściowe, kolejne YiY_i i końcową maskę AES.

L2. Kontrolowane ataki na testowe konstrukcje

Przygotowanie do zadań 1–2: W3: OTP i C1. Do zadań 3–5 oraz ataku afinicznego przeczytaj W6: grupy i skalary, W7: Schnorr, W8: ujawnienia i błędne warianty oraz C5. Najpierw wykonaj poprawny przebieg z zadań 1–2 w L3, a potem wróć do ataków na jego losowość.

Wszystkie ataki dotyczą własnych danych i lokalnych kluczy. Nie łącz się z cudzymi usługami.

  1. Przygotuj dwa ciągi bajtów tej samej długości. Zaszyfruj je jedną maską XOR. Porównaj XOR szyfrogramów z XOR wiadomości.
  2. Przy znanej pierwszej wiadomości odtwórz maskę i drugą wiadomość. Powtórz dla niezależnych masek i wyjaśnij, która równość przestaje ujawniać żądaną relację.
  3. W Pythonie zbuduj dwa transkrypty Schnorra ze wspólnym nonce i różnymi wyzwaniami. Zacznij od małej grupy z gmpy2, następnie powtórz eksperyment w obu grupach py_ecc. Oba transkrypty muszą przejść weryfikację. Odzyskaj skalar klucza przez odejmowanie i mnożenie przez odwrotność w Zq\mathbb Z_q, nie przez dzielenie zmiennoprzecinkowe.
  4. Zrób test kontrolny z niezależnymi nonce. Sprawdź, że ten sam wzór nie odtwarza klucza. Nie stwierdzaj, że każda para niezgodnych transkryptów musi dać inny wynik bez uwzględnienia prawdopodobieństwa przypadkowej zgodności.
  5. Osobno wykonaj przypadek znanego nonce przy niezerowym wyzwaniu. Nazwij różnicę między ujawnieniem, ustawieniem i resetem. Rachunek ataku jest pokrewny, ale interfejsy przeciwnika są różne.
OTP · dwie wiadomości, jedna maska

Lokalny rachunek na bajtach. Dwa wejścia szesnastkowe muszą mieć tę samą długość.

Maski szyfrujące

Gotowe do rozpoczęcia.

Nowe zobowiązanie, ten sam błąd. Wykonaj atak na odpowiedź afiniczną z W8. Wybierz następnie Schnorra i uruchom tę samą strategię. Wskaż w kodzie funkcję przeciwnika i sprawdź, że nie otrzymuje sekretu ani nonce. W raporcie oddziel niepowodzenie jednej strategii od dowodu ogólnego bezpieczeństwa.

Podszycie · obserwowany transkrypt i nowa rozmowa

MCL WebAssembly, BLS12-381. Punkty w G2G_2, skalary w Zq\mathbb Z_q. Klucze wyłącznie testowe.

Przypadek
Wspólny klucz publiczny A=gaA=g^a oczekuje

1. Pierwszy przebieg

Obserwacja uczciwej rozmowy.

DowodzącyWeryfikator
XX
oczekuje
cc
oczekuje
ss
oczekuje
s=u+a+cs=u+a+c
s=u+a⋅cs=u+a\cdot c

Weryfikacja oczekuje.

2. Drugi przebieg

OszustWeryfikator
X′X'
oczekuje
c′c'
oczekuje
s′s'
oczekuje
uu
oczekuje

Ujawniony nonce z pierwszej rozmowy. Sekret aa nadal nie został odczytany z urządzenia.

X′=X⋅grX'=X\cdot g^r

Weryfikacja oczekuje.

3. Sprawdzenie podszycia

Strategia korzysta z publicznej rozmowy i własnej losowości.

s′=s−c+r+c′s'=s-c+r+c'
rr oczekuje
gs′=X′⋅A⋅gc′g^{s'}=X'\cdot A\cdot g^{c'}
gs′≠X′⋅Ac′g^{s'}\ne X'\cdot A^{c'}

Oszust nie otrzymuje ani aa, ani uu.

Odrzucenie tej strategii nie jest pełnym dowodem bezpieczeństwa Schnorra.

Wynik 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 do rozpoczęcia.

Pełne wartości transkryptów

Serializacja MCL w zapisie szesnastkowym. Skróty na schemacie wskazują te same wartości.

WartośćSerializacja

W demonstratorze Schnorra wynik ekstrakcji jest porównywany z rzeczywistym kluczem testowym. Kontrola równości punktów to dodatkowy test, nie zamiennik porównania odzyskanego skalara.

Raport: transkrypty publiczne, założenie o losowości, wzór ekstrakcji, wynik porównania i kontrprzykład po usunięciu założenia.

L3. Identyfikacja i przepływ w urządzeniu

Przygotowanie: W6: grupy i skalary, W7: poprawny przebieg Schnorra i C5.1: poprawność. Zadania 1–3 nie wymagają pairingu. Część 4–5 wykonaj dopiero po W8: odpowiedź w grupie oraz L4.2: poprawne haszowanie do grupy. To rozszerzenie, nie warunek rozpoczęcia L3 ani L4.

Podział programu: odtwórz lokalne algorytmy identyfikacji. Stan dowodzącego przechowuj osobno od stanu weryfikatora. Check nie może korzystać z sekretu ani losowości dowodzącego tylko dlatego, że notebook zna wszystkie wartości. Drugą odpowiedź z tym samym stanem dopuszczaj wyłącznie w osobnym, jawnie podatnym eksperymencie resetu.

Rozgrzewka: ten sam Schnorr na małych liczbach

Najpierw czytamy A=gaA=g^a, X=guX=g^u, s=(u+a⋅c)modqs=(u+a\cdot c)\bmod q i gs=X⋅Acg^s=X\cdot A^c. Użyj gmpy2.powmod w podgrupie ⟨2⟩⊂Z23∗\langle 2\rangle\subset\mathbb Z_{23}^{*} rzędu q=11q=11. Dla a=3a=3, u=4u=4, c=5c=5 otrzymasz A=8A=8, X=16X=16, s=8s=8. Obie strony równania weryfikacji są równe 33 modulo 2323.

  • Sprawdź, że p=23p=23 i q=11q=11 są pierwsze, q∣(p−1)q\mid(p-1), g≠1g\ne1 oraz gq≡1(modp)g^q\equiv1\pmod p. Pierwszy rząd qq daje tu dokładnie podgrupę rzędu qq.
  • Oblicz ręcznie i w notebooku te same wartości. Weryfikator zna p,q,g,A,X,c,sp,q,g,A,X,c,s, ale nie dostaje aa ani uu.
  • Zmień odpowiedź o jeden modulo qq. Weryfikacja ma odrzucić ten transkrypt. Dla drugiego wyzwania zachowaj pierwszy transkrypt i porównaj dwa równania, jak w L2.

Te parametry są celowo niebezpieczne. Wystarczy sprawdzić 11 wykładników, aby odzyskać sekret. Nie służą do pomiaru bezpieczeństwa ani do porównania szybkości z BLS12-381. secrets.randbelow(q) losuje skalar. Dla klucza i nonce w naszym profilu użyj niezerowej wartości 1 + secrets.randbelow(q - 1).

Wykluczenie zerowego nonce jest częścią tego profilu laboratoryjnego. W W7 pierwszy rachunek HVZK dopuszcza całe ciało. Aby porównać rozkłady dla notebooka, zastosuj opisany tam symulator odrzucający neutralne zobowiązanie. Wyzwanie nadal losuj z całego Zq\mathbb Z_q. W przypadku c=0c=0 poprawna identyfikacja działa, ale wzór ataku dzielący przez cc nie ma zastosowania.

HVZK
honest-verifier zero knowledge. Zerowa wiedza wobec uczciwego weryfikatora.

Krzywa: najpierw działania, potem zapis potęgowy

W py_ecc.optimized_bls12_381 użyj generatorów G1 i G2. To nazwy konkretnych punktów biblioteki. Matematyczne G1,G2G_1,G_2 oznaczają grupy, a ich generatory oznaczamy P1,P2P_1,P_2 w zapisie addytywnym. Skalary redukuj modulo curve_order, nie modulo field_modulus, który dotyczy współrzędnych.

Zapis wykładu py_ecc (addytywnie) Nakładka (potęgowo)
gag^a multiply(P, a) g ** a
X⋅AcX\cdot A^c add(X, multiply(A, c)) X * (A ** c)
X/AX/A add(X, neg(A)) X / A
X=AX=A eq(X, A) X == A

Operatory mają reprezentować działania grupowe. __pow__ wywołuje mnożenie punktu przez skalar, __mul__ dodawanie punktów, a __truediv__ dodawanie punktu przeciwnego. __eq__ korzysta z eq, ponieważ różne współrzędne projektowe mogą reprezentować ten sam punkt. Nakładka przechowuje identyfikator grupy i odrzuca mieszanie G1G_1 z G2G_2. W Pythonie ^ oznacza XOR, nie potęgowanie. Nie potęguj współrzędnych i nie mnoż punktów współrzędna po współrzędnej.

Słownik obu notacji wyjaśnia ten sam most matematyczny. Nakładka nie zamienia krzywej w grupę liczb całkowitych. Zmienia tylko język zapisu programu.

Zadania i testy

  1. Zaimplementuj identyfikację Schnorra oddzielnie w G1G_1 i G2G_2. Dla i∈{1,2}i\in\{1,2\} wygeneruj sekret aa i A=a⋅PiA=a\cdot P_i. Wylosuj uu, wyślij X=u⋅PiX=u\cdot P_i, dopiero potem odbierz losowe cc od weryfikatora i oblicz s=(u+a⋅c)modqs=(u+a\cdot c)\bmod q. Najpierw użyj bezpośrednio funkcji multiply, add i eq.
  2. Weryfikuj s⋅Pi=X+c⋅As\cdot P_i=X+c\cdot A. Zmień odpowiedź, wyzwanie lub punkt zobowiązania i oczekuj odrzucenia. Następnie zaimplementuj nakładkę operatorów i wykonaj ten sam przebieg jako g ** s == X * (A ** c). Dla identycznych a,u,ca,u,c porównaj punkty i serializacje obu realizacji. Funkcja weryfikująca nie może odczytywać aa ani uu.
  3. Rozdziel stan dowodzącego i weryfikatora w kodzie. Wysyłaj serializowane dane. Po deserializacji kontroluj poprawność punktu, jego grupę i warunek q⋅P=Oq\cdot P=\mathcal O. Odrzucaj neutralny klucz publiczny i neutralne zobowiązanie w przyjętym profilu z niezerowymi sekretami. Sprawdź skalar 0≤s<q0\le s<q. Wewnętrznie nakładka musi nadal obsługiwać element neutralny i ujemne wykładniki. Dodaj test odrzucenia operacji na punktach z różnych grup.
  4. Przejdź do dydaktycznego wariantu pairingowego: B=ℋG1(enc⁡(X,c))B=\mathcal H_{G_1}(\operatorname{enc}(X,c)), S=(u+a⋅c)⋅BS=(u+a\cdot c)\cdot B. Sprawdź e(S,P2)=e(B,X+c⋅A)e(S,P_2)=e(B,X+c\cdot A). Dla zmienionego XX albo cc ponownie oblicz hasz po stronie weryfikatora.
  5. Rozdziel obliczenie a⋅Ba\cdot B w części chronionej od u⋅B+c⋅(a⋅B)u\cdot B+c\cdot(a\cdot B) w części roboczej. Opisz dane przekraczające granicę. Wskaż, że ani notebook, ani przeglądarka nie są HSM, a poprawne równanie nie jest pełnym dowodem odporności na wycieki.
    HSM
    hardware security module. Sprzętowy moduł bezpieczeństwa.

Zadanie 4 wykonaj po poznaniu haszowania do grupy w L4. Tu klucz i zobowiązanie wybieramy w G2G_2, a odpowiedź punktową w G1G_1. Matematyczne e(S,P2)=e(B,X+c⋅A)e(S,P_2)=e(B,X+c\cdot A) zapiszesz w py_ecc jako pairing(P2, S) == pairing(add(X, multiply(A, c)), B). API przyjmuje najpierw punkt G2G_2, potem punkt G1G_1. To kolejność argumentów biblioteki, nie zmiana definicji z wykładu. Modyfikacja odpowiedzi skalarnej na punktową zmienia konstrukcję. Sama zmiana notacji jej nie zmienia.

API
Application Programming Interface. Interfejs programistyczny, czyli określony zestaw dostępnych operacji.
Odpowiedź w grupie · granica modułu

Dydaktyczny podział obliczeń. Obie części wykonują się w tej samej przeglądarce. To nie jest izolacja HSM.

Transkrypt
Model części chronionej · sekret aKlucz publicznyChroniona operacjaCzęść roboczaOdpowiedź i weryfikacja
A=g2aA=g_2^a
Z=BaZ=B^a
X=g2u, B=ℋG1(enc⁡(X,c))X=g_2^u,\ B=\mathcal H_{G_1}(\operatorname{enc}(X,c))
S=Bu⋅ZcS=B^u\cdot Z^c

Zapis i obliczenia. Wzory schematu są multiplikatywne. MCL realizuje je na krzywej. Generator g2g_2 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 schemat używa również pairingu. W grupie docelowej zapis pozostaje multiplikatywny.

Gotowe do rozpoczęcia.

Oczekiwane wyniki: wariant skalarny ujawnia klucz po poznaniu nonce, jeśli c≠0c\ne0. Przeniesienie odpowiedzi do punktu zmienia to, co można odzyskać tym rachunkiem. Pełne twierdzenie wymaga właściwego modelu, haszowania i ograniczeń interfejsu chronionego modułu.

Pogłębienie: porównaj oryginalny i zmodyfikowany protokół w demonstratorach Schnorra i Okamoto. Zapisz typ każdej wiadomości oraz liczbę operacji grupowych. Nie nazywaj modelowej dekompozycji wierną realizacją konkretnego sprzętu.

L4. Podpisy i poprawne haszowanie do grupy

Przygotowanie: W9, C6.

  1. Zaimplementuj podpis Schnorra przez Fiat–Shamira w G1G_1 i G2G_2, najpierw addytywnie, potem z nakładką potęgową z L3. Zamiast interaktywnego wyzwania oblicz c=ℋ(enc⁡(suite,A,X,m))∈Zqc=\mathcal H(\operatorname{enc}(\mathrm{suite},A,X,m))\in\mathbb Z_q. Podpis to (X,s)(X,s), gdzie s=(u+a⋅c)modqs=(u+a\cdot c)\bmod q. Weryfikator sam odtwarza cc i sprawdza równanie. Uwzględnij grupę, klucz publiczny, zobowiązanie i dokładne bajty wiadomości. Stosuj kodowanie z długościami pól, kanoniczną serializację punktów oraz etykietę dziedziny. Powtórz rachunek w małej grupie modularnej z L3. Tak mały zakres wyzwania pozwala łatwo znaleźć kolizje i fałszerstwa, więc nie jest testem bezpieczeństwa.
  2. Zaimplementuj BLS w wariancie podpisu w G1G_1: σ=a⋅ℋG1(m)\sigma=a\cdot\mathcal H_{G_1}(m), A2=a⋅P2A_2=a\cdot P_2. Weryfikacja sprawdza e(σ,P2)=e(ℋG1(m),A2)e(\sigma,P_2)=e(\mathcal H_{G_1}(m),A_2).
    BLS
    Boneh–Lynn–Shacham. Nazwiska autorów schematu krótkich podpisów z pairingiem.
  3. Sprawdź poprawny podpis, inną wiadomość, inny klucz i zmodyfikowany podpis. Przeanalizuj deserializację, podgrupę i punkty neutralne. Sam pairing nie sprawdza całego kontraktu wejść.
  4. Utwórz opcjonalnie A1=a⋅P1A_1=a\cdot P_1. Sprawdź związanie wykładników: e(A1,P2)=e(P1,A2)e(A_1,P_2)=e(P_1,A_2). Ten dodatkowy klucz jest przydatny w pewnych konstrukcjach. Nie jest obowiązkowym elementem każdego wariantu BLS.
  5. Tylko w osobnej funkcji testowej zastąp hasz przez ℋbad(m)=μ(m)⋅P1\mathcal H_{\mathrm{bad}}(m)=\mu(m)\cdot P_1 z jawnym μ\mu. Wykonaj atak z C6. Nie używaj tego wariantu jako implementacji BLS.
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.

Dwie różne funkcje haszujące. W podpisie Schnorra ℋ\mathcal H daje skalar. Notebook pokazuje jawny profil dydaktyczny SHAKE-256 z dłuższym wyjściem i redukcją modulo qq. To nie haszowanie do punktu. Dla BLS użyj hash_to_G1(message, DST, hashlib.sha256) z py_ecc.bls.hash_to_curve. Oznaczamy je ℋG1\mathcal H_{G_1}. Funkcja hash_to_G2 daje odpowiednio punkt drugiej grupy. DST jest jawną etykietą dziedziny. Wybierz ją, zapisz i stosuj identycznie po obu stronach. Nie zastępuj haszowania do krzywej przez jawny skalar razy znany generator. Kod py_ecc 8.0.0 i RFC 9380 opisują tę operację.

SHAKE-256
Secure Hash Algorithm KECCAK. Nazwa funkcji z rodziny Keccak o wybieranej długości wyjścia. Wariant 256 nie ogranicza wyniku do 256 bitów.
DST
Domain Separation Tag. Etykieta rozdzielająca zastosowania funkcji haszującej.
RFC
Request for Comments. Dokument z serii opisującej m.in. protokoły internetowe. Nie każdy RFC jest standardem.

Porównanie z przeglądarką: demonstracja używa mcl.hashAndMapToG1 i własnej etykiety dziedziny. Nie zakładamy, że jej punkty, serializacja lub podpisy będą bajtowo zgodne z profilem Python. Wspólna krzywa nie wystarcza do interoperacyjności. Ta wymaga zgodnych parametrów, hasza, kodowania i wektorów testowych. Żadna z własnych instancji dydaktycznych nie jest automatycznie standardową ciphersuite BLS.

Pogłębienie: przygotuj testy własnościowe i pomiary oddzielnie dla haszowania, podpisu i weryfikacji. Obejmij wiadomości puste, długie i zawierające polskie znaki. Zmienna długość tekstu nie powinna zmieniać typu klucza ani podpisu.

Podpis na własnej warstwie algebraicznej

  1. Jeden interfejs, wybrane grupy. Zastosuj arytmetykę z L0a do podpisu Schnorra. Prowadzący wybiera podgrupę multiplikatywną ciała albo podgrupę punktów krzywej. Opisz Setup, KeyGen, Sign i Verify oraz parametry grupy o pierwszym rzędzie qq. Zachowaj profil c=ℋ(enc⁡(suite,A,X,m))c=\mathcal H(\operatorname{enc}(\mathrm{suite},A,X,m)) z zadania 1. Wylosuj świeże u←$Zq∗u\overset{\$}{\leftarrow}\mathbb Z_q^*, oblicz X=guX=g^u, a następnie s=(u+a⋅c)modqs=(u+a\cdot c)\bmod q. Zweryfikuj gs=X⋅Acg^s=X\cdot A^c. Zapis potęgowy na krzywej oznacza działania addytywne udostępnione przez wspólny interfejs z L3. Zachowaj jawny profil hasza i kanonicznego kodowania. Przetestuj pustą wiadomość, zmieniony klucz, zmienioną wiadomość i błędny element grupy. Nie utożsamiaj rozmiaru współrzędnych z poziomem bezpieczeństwa.
  2. Dwa formaty podpisu Schnorra. Oprócz (X,s)(X,s) obsłuż wariant (s,c)(s,c). Weryfikator oblicza X′=gs⋅A−cX'=g^s\cdot A^{-c} i ponownie wyznacza hasz krotki z X′X'. Akceptuje tylko po kontroli kodowania, dopuszczalnych wartości oraz zgodności otrzymanego cc z obliczonym haszem. Sprawdź zgodność obu wariantów dla tych samych wiadomości i kluczy. Przy konwersji do (s,c)(s,c) użyj już wyliczonego cc, nie losuj nowego. Pokaż przykład zmiany cc, którą Verify odrzuca. Sposób kodowania grupy, klucza, zobowiązania i wiadomości musi być identyczny po obu stronach. Przygotowanie rachunkowe: C6.6.

Wynik pracy: dwa jawne formaty podpisu, testy obu weryfikatorów oraz tabela rozmiarów. Są to profile dydaktyczne. Nie deklaruj zgodności ze standardem ani z cudzym serwerem tylko dlatego, że oba używają nazwy „Schnorr”.

L5. Ustalanie klucza, kontekst i potwierdzenie

Przygotowanie: W5: MAC, W10: DH, SIGMA i NAXOS, C7. Do zadania 5 potrzebny jest model ujawnień z dodatku C.

SIGMA
SIGn-and-MAc. Podejście łączące podpis cyfrowy i kod uwierzytelnienia wiadomości.
NAXOS
NAXOS. Nazwa własna protokołu uwierzytelnionej wymiany klucza, nie skrót rozwijany do angielskich słów.

Najpierw wykonujemy rachunek, a dopiero potem rozważamy uwierzytelnienie i model przeciwnika. Poniższy demonstrator realizuje algebraiczny rdzeń NAXOS, wyprowadzanie klucza i potwierdzenie HMAC. Nie implementuje pełnego sieciowego systemu AKE ani wszystkich interfejsów jego dowodu.

HMAC
Hash-based Message Authentication Code. Kod uwierzytelnienia wiadomości oparty na funkcji haszującej. Przyrostek SHA-256 wskazuje użyty hasz.
AKE
Authenticated Key Exchange. Uwierzytelniona wymiana klucza.

Prostszy wariant na początek: zadanie 6, podstawowy DH, wykorzystuje własną arytmetykę z L0a. Dopiero potem przejdź do zadań o NAXOS lub do lokalnego testu współpracy programów.

Własną realizację przygotuj w notebooku. Użyj py_ecc do operacji grupowych, cryptography do HKDF oraz hmac i hashlib do HMAC-SHA-256. Zdefiniuj własny jednoznaczny profil bajtowy. Zapisz w raporcie etykiety i kolejność pól. Zgodność wyników stron w Pythonie nie wymaga zgodności bajtowej z odrębnym demonstratorem MCL.

Kolejność obliczeń: zadania 1–2 tworzą wspólną krotkę, której używają zadania 3–4. Do wyprowadzania klucza przejdź dopiero po sprawdzeniu zgodności trzech składników i ich kolejności.

HKDF przed zadaniem 3. HKDF wyprowadza klucze z wejściowego materiału kluczowego, oznaczanego IKM. Etap Extract łączy ten materiał z solą salt przez HMAC i daje klucz pośredni PRK. Etap Expand używa PRK, kontekstu info i żądanej długości wyjścia. Sól nie musi być tajna. Kontekst wiąże wynik z konkretnym zastosowaniem. Te dwa etapy opisuje RFC 5869, rozdział 2.

IKM
Input Keying Material. Wejściowy materiał kluczowy.
PRK
Pseudorandom Key. Klucz pseudolosowy, czyli wynik etapu Extract w HKDF.

W funkcji derive lokalnego kodu demonstratora IKM jest zapisem UTF-8 tablicy JSON z etykietą PWr-Crypto-II-v1/NAXOS-material i trzema serializacjami punktów w ustalonej kolejności. salt jest zapisem UTF-8 napisu PWr-Crypto-II-v1. info koduje etykietę celu oraz kontekst obejmujący tożsamości, role, klucze publiczne i wkłady sesyjne. Każde wywołanie daje 32 bajty. Etykiety session i confirmation rozdzielają klucz sesji od klucza HMAC. Przy odtwarzaniu demonstratora zachowaj dokładnie jego kodowanie, także zagnieżdżony zapis kontekstu. Jest to jawny profil dydaktyczny, nie standardowy format NAXOS.

JSON
JavaScript Object Notation. Tekstowy format zapisu danych strukturalnych.
  1. Wygeneruj stałe sekrety a,ba,b oraz niezależne zalążki rA,rBr_A,r_B. Wyprowadź x=ℋ(enc⁡(rA,a))x=\mathcal H(\operatorname{enc}(r_A,a)) i y=ℋ(enc⁡(rB,b))y=\mathcal H(\operatorname{enc}(r_B,b)) z rozdzieleniem dziedziny.
  2. Oblicz klucze publiczne i wkłady sesyjne. Porównaj po stronach uporządkowane krotki (Ya,Bx,Yx)(Y^a,B^x,Y^x) i (Ay,Xb,Xy)(A^y,X^b,X^y). W implementacji addytywnej odpowiadają im mnożenia punktów przez skalary.
  3. Wyprowadź z krotki klucz przez HKDF-SHA-256. Zwiąż tożsamości, role i oba wkłady publiczne z kontekstem. To dydaktyczna instancja KDF, nie wyrocznia losowa z dowodu NAXOS.
    KDF
    Key Derivation Function. Funkcja wyprowadzania kluczy.
  4. Wyprowadź oddzielny klucz potwierdzenia, oblicz HMAC transkryptu i zweryfikuj go u partnera. Zmień tożsamość lub rolę tylko po jednej stronie i oczekuj niezgodności. Wyjaśnij, dlaczego samo potwierdzenie nie zastępuje zaufanego powiązania tożsamości z kluczem.
  5. Przygotuj tabelę ekspozycji z C7. Wskaż różnicę między ujawnieniem zalążka i gotowego wykładnika. Nie nazywaj demonstratora dowodem eCK.
    eCK
    extended Canetti–Krawczyk. Rozszerzony model Canettiego–Krawczyka. Dopuszczalne ujawnienia określa jego definicja.
NAXOS · zgodność trzech składników

Rachunek grupowy MCL oraz HKDF-SHA-256 i HMAC w WebCrypto. To profil dydaktyczny, nie pełna implementacja modelu eCK.

Kontekst

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 do rozpoczęcia.

Następny etap: SIGMA. Zaimplementuj osobny profil dydaktyczny z kluczami podpisu, których autentyczność została wcześniej zapewniona. Podpisuj wkłady DH, potwierdzaj tożsamość MAC zgodnie z W10 i rozdziel klucz sesji od klucza MAC. Zapisz momenty akceptacji. Odrzucaj zmienione wkłady i nieznany klucz partnera. Nie przedstawiaj tego jako implementacji IKE.

IKE
Internet Key Exchange. Protokół uzgadniania kluczy i parametrów ochrony połączenia.

Pogłębienie dowodowe: dla jednej uczciwej wymiany bez ujawnień zapisz redukcję DDH. Następnie wskaż, które odpowiedzi symulatora przestają być proste po dopuszczeniu aktywnych sesji i ekspozycji. To początek analizy AKE, nie dowód otrzymany z testu zgodności kluczy.

DDH
Decisional Diffie–Hellman. Decyzyjny problem Diffiego–Hellmana.

Źródła: NAXOS, SIGMA, HKDF.

Od własnego DH do współpracy programów

  1. Diffie–Hellman w wybranej grupie. Dla parametrów G=⟨g⟩G=\langle g\rangle o pierwszym rzędzie qq zaimplementuj generowanie sekretów x,y←$Zq∗x,y\overset{\$}{\leftarrow}\mathbb Z_q^*, wkładów X=gxX=g^x, Y=gyY=g^y i sekretów ZA=YxZ_A=Y^x, ZB=XyZ_B=X^y. Użyj własnych działań z L0a w jednej grupie wskazanej przez prowadzącego. Rozszerzeniem jest drugi wariant: podgrupa Fp∗\mathbb F_p^*, F2k∗\mathbb F_{2^k}^*, Fpk∗\mathbb F_{p^k}^* albo krzywej. W raporcie podaj rząd całej grupy, rząd podgrupy, generator i sposób sprawdzenia parametrów. Przed obliczeniem sekretu sprawdzaj przynależność otrzymanego elementu do właściwej podgrupy i odrzucaj element neutralny. Dla krzywej sprawdzaj także przynależność do krzywej. Potwierdź ZA=ZBZ_A=Z_B, a następnie wyprowadź klucz przez HKDF z kontekstem obejmującym parametry i uporządkowane wkłady. Pokaż w teście, dlaczego zaakceptowanie neutralnego wkładu daje znany sekret. DH sam nie uwierzytelnia partnera. Pierwszy rząd podgrupy nie jest dowodem trudności CDH ani DDH.
    CDH
    Computational Diffie–Hellman. Obliczeniowy problem Diffiego–Hellmana.
  2. Lokalny test interoperacyjności. W parze przygotujcie dwa niezależne programy używające DH z zadania 6 oraz podpisów z L4. Uzgodnijcie profil bajtowy z L0a.6. Autentyczne klucze weryfikacji podpisów wymieńcie wcześniej zaufanym kanałem. Otrzymanie klucza w tej samej niezaufanej wiadomości co podpis nie ustanawia zaufania. Podpisujcie etykietę protokołu, identyfikator sesji, role, parametry i oba wkłady DH. Zachowajcie osobne klucze podpisu i sekrety sesyjne DH. Odrzucajcie zmieniony wkład, niewłaściwy podpis, nieznany klucz i wiadomość z innej sesji. Do potwierdzenia użyjcie HMAC całego transkryptu z odrębnym kluczem wyprowadzonym przez HKDF. Nie przesyłajcie wspólnego sekretu jako komunikatu. Zapiszcie pełny uczciwy przebieg i przebiegi odrzucone. Programy mogą wymieniać pliki albo komunikować się wyłącznie na localhost. Nie jest potrzebny zewnętrzny serwer konkursowy.

Granica wniosku: zadanie 7 sprawdza kodowanie, związanie podpisu z sesją i działanie testów negatywnych. Nie daje dowodu bezpieczeństwa nowego AKE. Do analizy pełnego protokołu służą SIGMA i NAXOS oraz ich modele z wykładu.

L6. Przepływ etykiet w obwodzie

Przygotowanie: W6: grupy i problemy DH, W12: OT i prywatny widok, W12a: obwód i etykiety oraz C12.

OT
Oblivious Transfer. Transfer utajniony. Odbiorca poznaje wybraną wartość, a nadawca nie poznaje jego wyboru.

Prześledź animację garbled circuits, a potem odtwórz obwód w Pythonie. Użyj secrets do etykiet, jawnie zdefiniowanej funkcji wyprowadzania klucza z etykiet wejść i numeru bramki oraz AESGCM do tabel. Zachowaj rozdzielenie stanów konstruktora i wykonawcy. Punkt odniesienia: kod demonstratora. To lokalny model z symulowanym OT, nie implementacja bezpiecznego protokołu między dwiema maszynami.

  1. Wykonaj wszystkie osiem kombinacji wejść. Dla każdej zapisz wynik jawnego obliczenia i odczytanej etykiety. Porównaj je automatycznie.
  2. Dwa razy przygotuj te same bity wejściowe. Sprawdź, czy wynik logiczny jest taki sam, a szyfrogramy i etykiety świeże. Nie utożsamiaj zmiany szyfrogramu ze zmianą funkcji.
  3. Włącz uszkodzenie wiersza AND. Sprawdź, że nie pojawia się wynik XOR ani nowa końcowa etykieta. Zmiana szyfrogramu ma powodować odrzucenie, nie użycie poprzedniego wyniku.
    AND
    and. I, czyli koniunkcja logiczna. To angielskie słowo, nie akronim. Bramka AND zwraca 1 tylko wtedy, gdy oba wejścia mają wartość 1.
  4. Przygotuj nowy obwód ze świeżymi etykietami. Sprawdź, że starych etykiet nie można użyć jako aktualnego wejścia. Zachowaj oba przebiegi w raporcie. W animacji dodatkowo zatrzymaj obliczenia i zmień wejście. Sprawdź, że nie przychodzi opóźniony wynik starego przebiegu.
  5. Opisz granice demo. Wskaż, gdzie OT jest symulowane i które dane zna administrator jednej przeglądarki. Nie przedstawiaj testu funkcjonalnego jako dowodu prywatności dwóch odrębnych osób.

Raport: tabela wejść i wyników, przykład świeżych tabel, test negatywny oraz opis różnicy między widokiem wykonawcy a całym stanem strony. Rozszerzenie: oszacowanie komunikacji dla Free-XOR i half-gates. Nie zmieniaj korelacji etykiet bez zmiany i analizy całej konstrukcji.

L7. Podpisujący współpracują, sekret pozostaje podzielony

Przygotowanie: W13: udziały Shamira, W13a: protokół progowy oraz C13. Zadanie 3 wykorzystuje wzór wyprowadzony w C13.4.

Odtwórz w Pythonie próg 2 z 3. Wielomiany i interpolację licz modulo curve_order, a zobowiązania i odpowiedzi grupowe przez py_ecc. Przed testem w notebooku porównaj wzory z C13. Nie rekonstruuj sekretu w funkcji weryfikującej.

  1. Przetestuj każdy dopuszczalny podzbiór i jeden podzbiór zbyt mały. Sprawdź częściowe równania oraz równanie końcowe.
  2. Zmień odpowiedź jednego uczestnika. W raporcie odróżnij zlokalizowanie błędnego udziału od zdolności dokończenia sesji bez niego. Obecny demonstrator odrzuca sesję.
  3. W lokalnej kopii testowej powtórz nonce jednego uczestnika dla dwóch wyzwań i tej samej listy. Odtwórz jego udział wzorem z ćwiczeń, następnie potwierdź go przez klucz weryfikacyjny udziału.
  4. Zweryfikuj interfejs końcowego weryfikatora. Nie powinien otrzymywać wielomianu dealera, sekretu ani nonce.
  5. Opisz, czego brakuje do wdrożenia FROST. Nie nazywaj testowej algebry dla uczciwych uczestników gotowym podpisem odpornym na złośliwego koordynatora.
    FROST
    Flexible Round-Optimized Schnorr Threshold. Elastyczny progowy protokół Schnorra ze zoptymalizowaną liczbą rund.

L8. Iloczyn skalarny bez deszyfrowania u wykonawcy

Przygotowanie: W6: typy grup i pairing, W16: szyfrowanie homomorficzne i zakres odczytu oraz C14.

Odtwórz równania demonstratora homomorficznego w py_ecc. W grupach źródłowych użyj operacji na punktach. W grupie docelowej wynik pairingu jest elementem FQ12 i zapis multiplikatywny oznacza już rzeczywiste mnożenie elementów ciała. Nie stosuj do niego nakładki punktowej z L3. Zachowaj mały jawny zakres dekodowania. To model ograniczonej funkcjonalności, nie ogólne FHE.

FQ12
degree-12 finite-field extension. Opis typu bibliotecznego reprezentującego element rozszerzenia ciała skończonego stopnia 12.
FHE
Fully Homomorphic Encryption. W pełni homomorficzne szyfrowanie.
  1. Przetestuj liczby dodatnie, ujemne, zera oraz krańce zakresu. Porównaj odczyt szyfrogramu z wynikiem jawnym.
  2. Przejrzyj funkcję wykonawcy. Dostaje tylko szyfrogramy. Uzasadnij, dlaczego podanie jej jawnego wyniku do późniejszego „odczytu” byłoby błędnym testem.
  3. Sprawdź odrzucenie GT×G2G_T\times G_2 i dodawania szyfrogramów z różnych grup. To test zgodności typów, nie ograniczenie liczby pierwszopoziomowych mnożeń.
  4. Przygotuj szyfrogram zera zamiast żądanego wyniku. Wyjaśnij, dlaczego poprawne deszyfrowanie nie wykrywa samo zmiany zadania.
  5. Porównaj interfejs z przykładem Herumi. Oddziel szyfrowanie, ewaluację, składanie wyników i dekodowanie. Nie porównuj czasów różnych konfiguracji tak, jakby mierzyły te same parametry.

L9. Raport kosztów zamiast pojedynczego czasu

Przygotowanie: W17: rachunek kosztów i C15.1: koszt BLS i Schnorra. Do zadania 4 wróć także do W12a: komunikacja obwodu i OT.

Najpierw zmierz własny kod Python przez time.perf_counter_ns(). Oddziel działania w G1G_1, działania w G2G_2, haszowanie do grupy, pairing oraz pełną weryfikację. Pomiar pairingu musi jasno wskazywać, czy obejmuje końcowe potęgowanie. Domyślne pairing w py_ecc je wykonuje.

  1. Zapisz system, procesor, wersję Pythona i pakietów, stan zasilania oraz parametry grupy. Wykonaj rozgrzewkę, a potem co najmniej trzy serie pomiarów. Podaj liczbę wywołań w serii. Nie wliczaj wyświetlania tabeli w notebooku do czasu operacji.

  2. Przedstaw mediany w milisekundach na operację. Zachowaj jednakową liczbę miejsc po przecinku i wyrównanie liczb do separatora dziesiętnego.

  3. Zbuduj estymację podpisywania i weryfikowania z liczby operacji. Porównaj ją z bezpośrednim pomiarem kompletnego wywołania. Wskaż pominięte koszty.

  4. Osobno licz bajty i rundy komunikacji. W przykładzie obwodu nie przypisuj OT zerowego kosztu tylko dlatego, że lokalne demo zastępuje je usługą.

  5. Wyjaśnij, dlaczego pomiar szybkości nie sprawdza odporności na kanały boczne, poprawności redukcji ani poziomu bezpieczeństwa parametrów.

  6. Pogłębienie: koszt zależny od wykładnika. Dla własnego algorytmu square-and-multiply, czyli kolejnych podniesień do kwadratu i mnożeń, policz oddzielnie liczbę operacji i czas wykonania. Najpierw porównaj wykładniki o tej samej długości bitowej i różnej liczbie jedynek. Następnie osobno zmieniaj długość. Wykonaj analogiczny eksperyment dla mnożenia punktu przez skalar. Ustal budżet powtórzeń, przeplataj kolejność przypadków i pokaż rozrzut wyników. Nie wliczaj generowania danych ani wypisywania raportu. Porównaj z wariantem drabinkowym o stałej liczbie kroków dla ustalonej szerokości skalara. Zbadaj rozgałęzienia i operacje na pamięci, nie tylko liczbę mnożeń. Stała liczba działań nie zapewnia stałego czasu arytmetyki dużych liczb w Pythonie. Brak widocznej różnicy w próbce nie dowodzi odporności na kanały boczne. Przygotowanie: C15.6.

Wynik zadania 6: opis dwóch algorytmów, licznik operacji, tabela pomiarów oraz wniosek ograniczony do badanego środowiska. Badamy wyłącznie własny proces i klucze testowe.

L10. Dwie identyfikacje, dwa sposoby symulacji

Przygotowanie: porównanie protokołów. Korzystaj wyłącznie z lokalnych kluczy testowych.

Przygotuj obie strony protokołów jako oddzielne funkcje Pythona. Użyj operacji grupowych z L3 i osobnych etykiet dla różnych zastosowań hasza. Animacja służy do porównania kolejności komunikatów, a raport zawiera transkrypty wyliczone przez własny kod.

  1. Uruchom oba uczciwe przepływy krok po kroku. Zapisz kolejność komunikatów, ich typy i moment, w którym weryfikator zna oczekiwaną odpowiedź.
  2. Porównaj uczciwego Schnorra z symulatorem mającym tylko parametry i klucz publiczny. Sprawdź równanie na wszystkich otrzymanych transkryptach. Test skończonej próbki nie zastępuje dowodu równości rozkładów z wykładu.
  3. Wybierz wyzwanie Schnorra związane z haszem. Zapisz dwa wyniki: równanie grupowe oraz zgodność wyzwania z haszem. Dlaczego pierwszy może być prawdziwy, a drugi fałszywy?
  4. W Stinsonie–Wu ustaw błędny skrót. Potwierdź, że odpowiedź nie zostaje wysłana. Następnie ujawnij jedynie losowość weryfikatora. Odtwórz akceptowaną odpowiedź bez użycia sekretu dowodzącego.
  5. W raporcie oddziel uczciwego uczestnika, podsłuchującego, złośliwego weryfikatora i atakującego znającego rr. Nie przenoś uprawnień między tymi modelami.

Oddaj: po jednym pełnym zapisie dla każdego przypadku, równania weryfikacji oraz krótkie uzasadnienie, co zapis mówi osobie trzeciej. Wyjaśnij też, dlaczego programowanie wyroczni w dowodzie nie jest funkcją udostępnioną użytkownikowi hasza.

L11. Szyfrogram zmienia się bez ujawnienia wiadomości

Przygotowanie: reenkrypcja, sieci miksujące. Zaimplementuj opisane warianty w Pythonie z py_ecc. Zachowaj typy z wykładu, szczególnie w wariancie pairingowym AFGH. Istniejące demonstratory MCL pozostają punktem porównania przepływów. Nie uruchamiamy zewnętrznego serwera ani sieci anonimowej.

AFGH
Ateniese–Fu–Green–Hohenberger. Nazwiska autorów omawianego schematu reenkrypcji z pairingiem.
  1. ElGamal. Zapisz szyfrogram przed rerandomizacją i po niej. Odszyfruj oba i porównaj wiadomości. W kolejnych powtórzeniach sprawdź również zmianę serializacji.
  2. BBS. Wyznacz klucz delegacji, przekształć szyfrogram i odszyfruj go jako Bob. Osobno oblicz sekret Alicji z sekretu Boba i klucza delegacji. To kontrolowana demonstracja koluzji, nie funkcja publicznego proxy.
    BBS
    Blaze–Bleumer–Strauss. Nazwiska autorów omawianej reenkrypcji. Nie chodzi o generator Blum–Blum–Shub.
  3. AFGH. Sprawdź odczyt pierwotnej pary przez Alicję i odczyt przekształconej pary przez Boba. Zapisz typy grupowe. Próba ponownej reenkrypcji szyfrogramu pierwszego poziomu ma zostać odrzucona przez kontrolę interfejsu.
  4. Nieprawidłowy sekret. Porównaj wynik z wiadomością testową. Wyjaśnij, skąd demonstrator wie, że wynik jest niezgodny, i dlaczego sam nieposiadający wiadomości odbiorca nie zawsze mógłby to stwierdzić.
  5. Partia czterech wiadomości. Wykonaj trzy warianty: sama permutacja, sama rerandomizacja, obie operacje. Zachowaj wszystkie partie pośrednie. Odsłoń pochodzenie dopiero po zapisaniu własnej próby powiązania wejść z wyjściami.
  6. Integralność partii. W lokalnej kopii eksperymentu powiel jedną pozycję i pomiń inną. Wykaż, że samo poprawne deszyfrowanie nie wykrywa naruszenia. Zapisz relację dla dowodu shuffle, którego demonstrator nie implementuje.

Oddaj: tabelę wejść i wyjść, wyniki dodatnie i ujemne oraz granice demonstracji. Punkty reprezentują wiadomości algebraiczne. Nie opisuj tego kodu jako gotowego szyfrowania plików ani dowodu anonimowości.

L12. RSA w bibliotece i FDH w symulacji

FDH
Full Domain Hash. Haszowanie o pełnej dziedzinie wyników.

Przygotowanie: W10b: RSA, OAEP i PSS. Przed zadaniami 5–7 przeczytaj W10c: tabela symulatora FDH i wykonaj zadania 5–7 z C17.

OAEP
Optimal Asymmetric Encryption Padding. Kodowanie wiadomości przed szyfrowaniem asymetrycznym.
PSS
Probabilistic Signature Scheme. Probabilistyczny schemat podpisu.

Cel: odróżnić działający standardowy schemat od arytmetycznego modelu dowodu. Wszystkie dane i klucze w tym laboratorium są testowe.

  1. Uruchom RSA-OAEP i RSA-PSS w Pythonie, korzystając z modułu RSA biblioteki cryptography. Zapisz dwa szyfrogramy i dwa podpisy tej samej wiadomości. Sprawdź, czy różnią się ich bajty oraz czy odczyt i weryfikacja dają właściwe wyniki. Porównaj mechanizm z demonstratorem.
  2. Zbadaj odrzucenie innej etykiety OAEP, zmienionej wiadomości i zmienionego podpisu. W raporcie rozdziel błąd deszyfrowania od negatywnej weryfikacji podpisu.
  3. Użyj osobnych kluczy dla obu celów. Zapisz moduł, wykładnik publiczny, hash, hash MGF1 i długość soli PSS. Ustaw SHA-256 dla hasza i MGF1 oraz 32 bajty soli PSS. Nie implementuj produkcyjnego kodowania RSA samodzielnie. gmpy2 wykorzystaj osobno do małego modelu arytmetycznego FDH, a nie zamiast OAEP lub PSS.
    MGF1
    Mask Generation Function. Funkcja generowania maski. MGF1 oznacza konkretną konstrukcję tej funkcji.
    SHA-256
    Secure Hash Algorithm. Algorytm bezpiecznego haszowania. W nazwie SHA-256 liczba oznacza 256-bitowy wynik.
  4. Sprawdź granicę 190 bajtów OAEP w przyjętym profilu 2048/SHA-256. Przetestuj dokładnie 190 oraz 191 bajtów i tekst zawierający polskie znaki. Raportuj długość UTF-8, nie tylko liczbę znaków.
  5. Prześledź symulator FDH krok po kroku. Zachowaj tabelę po każdym zapytaniu. Zbadaj sukces, żądanie podpisu celu i nietrafione fałszerstwo.
  6. Własny symulator musi mieć powtarzalne odpowiedzi dla tej samej wiadomości. Dodaj test, w którym pierwsze zapytanie jest żądaniem podpisu. Redukcja nie może dostawać klucza prywatnego.
  7. Oddziel generator testowego fałszerstwa od redukcji. Mały przykład demonstratora zna świadka administracyjnie, aby pokazać implikację „gdyby istniał taki fałszerz”. Nie przedstawiaj tego jako złamania RSA-FDH.
    RSA-FDH
    Rivest–Shamir–Adleman with Full Domain Hash. Podpis RSA z haszowaniem do pełnej dziedziny wyników.

Raport: parametry, wejścia, wyniki, testy negatywne i tabela symulacji. Wyjaśnij, które obserwacje testują kod, a które zdania wymagają dowodu w modelu wyroczni losowej.

L13. Podpis, wyzwanie i odbiorca logowania

Przygotowanie: W10d: WebAuthn i podpis ECDSA, W10e: OIDC, PKCE i tokeny oraz C18.

WebAuthn
Web Authentication. Standard uwierzytelniania w aplikacjach internetowych z użyciem klucza publicznego.
OIDC
OpenID Connect. Warstwa uwierzytelniania oparta na mechanizmie delegowania dostępu OAuth 2.0.
PKCE
Proof Key for Code Exchange. Powiązanie wymiany kodu autoryzacyjnego z sekretem klienta.

Cel: sprawdzić, dlaczego poprawny podpis i akceptacja logowania są różnymi wynikami. Laboratorium nie wymaga danych kont uczelnianych, prawdziwego dostawcy SSO ani prywatnego klucza użytkownika.

SSO
Single Sign-On. Jednokrotne logowanie wykorzystywane przez wiele usług.

W notebooku odtwórz kontrole odbiorcy i testowe podpisy ECDSA P-256 przez cryptography, nie przez BLS12-381 z py_ecc. Użyj hashlib do skrótów i PKCE. decode_dss_signature i encode_dss_signature pozwalają poprawnie przejść między liczbami r,sr,s a DER. To model danych i walidacji, nie prawdziwy uwierzytelniacz FIDO ani zastępstwo przeglądarkowego API WebAuthn.

P-256
P-256. Nazwa krzywej nad ciałem pierwszym o 256-bitowym module. To identyfikator parametrów, nie rozwinięcie akronimu.
DER
Distinguished Encoding Rules. Jednoznaczne reguły kodowania danych ASN.1.
FIDO
Fast IDentity Online. Rodzina standardów uwierzytelniania. FIDO2 łączy standard przeglądarkowy WebAuthn z protokołem CTAP.

Kodowanie przed zadaniem 4. Podpis ECDSA składa się z dwóch liczb r,sr,s. W formacie WebCrypto dla P-256 każda zajmuje dokładnie 32 bajty, więc ich połączenie ma 64 bajty. DER, czyli jednoznaczne kodowanie struktur ASN.1, zapisuje sekwencję dwóch liczb całkowitych wraz ze znacznikami typów i długościami. Dodatnia liczba z ustawionym najwyższym bitem potrzebuje początkowego bajtu 00, aby nie została odczytana jako ujemna. Długość podpisu DER może się więc zmieniać. Na przykład same liczby r=128r=128, s=1s=1 mają zapis DER 30 07 02 02 00 80 02 01 01. 30 07 rozpoczyna sekwencję siedmiu bajtów, a 02 oznacza liczbę całkowitą. To przykład kodowania, nie poprawny podpis wskazanej wiadomości. Format wymagany przez WebAuthn opisuje specyfikacja, rozdział 6.5.5.

ASN.1
Abstract Syntax Notation One. Notacja opisu abstrakcyjnych struktur danych.
  1. W modelu odpowiedzi WebAuthn wykonaj wszystkie przypadki. Dla każdego zapisz wynik podpisu i wynik decyzji RP.
    RP
    Relying Party. Usługa polegająca na wyniku uwierzytelnienia.
  2. Rozkoduj 37-bajtowe dane uwierzytelniacza z podstawowego przykładu: 32 bajty skrótu RP ID, 1 bajt flag, 4 bajty licznika big-endian. Nie uogólniaj tej długości na odpowiedzi z rozszerzeniami lub danymi rejestracji.
    ID
    identifier / identification. Identyfikator / identyfikacja, zależnie od nazwy pola. RP ID identyfikuje usługę, a ID Token przekazuje informację o uwierzytelnieniu.
  3. Przelicz SHA-256 dokładnych bajtów clientDataJSON. Nie serializuj ponownie obiektu przed weryfikacją, bo odstępy lub kolejność pól mogą zmienić podpisane bajty.
  4. Model tworzy ECDSA w formacie WebCrypto. Wyjaśnij różnicę między 64 bajtami r∥sr\Vert s a DER używanym dla ES256 w WebAuthn. Nie przesyłaj jednego formatu do parsera drugiego.
    ES256
    ECDSA using P-256 and SHA-256. Identyfikator podpisu ECDSA na krzywej P-256 z haszem SHA-256.
  5. W przepływie OIDC porównaj zły state, zły weryfikator PKCE, innego odbiorcę i inny nonce. Wskaż etap przerwania. Poprawny podpis tokenu dla innej aplikacji nie powinien otwierać sesji.
  6. Przelicz PKCE S256 i sprawdź wektor z dodatku B RFC 7636. Dekoduj części JWT lokalnie. Nie wysyłaj prawdziwych tokenów do zewnętrznych dekoderów.
    S256
    SHA-256 code challenge method. Identyfikator metody tworzenia wyzwania PKCE przez hasz SHA-256.
    JWT
    JSON Web Token. Format tokenu przenoszącego zestaw stwierdzeń.
  7. Dodaj testy wygasłego tokenu, nieznanego wystawcy i ponownego wykorzystania kodu. Zapisz brakujące elementy pełnego wdrożenia: TLS, magazyn transakcji, rejestrację poświadczeń, zaufaną konfigurację kluczy, politykę sesji i odzyskiwanie konta.
    TLS
    Transport Layer Security. Protokół ochrony komunikacji, zapewniający m.in. poufność i integralność.

Raport: tabela przypadków, podpisane bajty, warunek odrzucenia i dokument źródłowy. Testy wykonuj wyłącznie na własnych lokalnych instancjach. Negatywne przypadki demonstratora nie są próbą przełamania prawdziwego uwierzytelniacza FIDO.

Rozszerzenie: MCL i wrappery studenckie

MCL jest zoptymalizowaną biblioteką C++ do operacji grupowych i pairingów. Kosztowne obliczenia wykonuje kod natywny, zamiast realizować całą arytmetykę w Pythonie. To dobry wybór do długich serii podpisywania, weryfikacji i eksperymentów wymagających wielu powtórzeń. Rzeczywiste przyspieszenie względem py_ecc zmierz dla tego samego schematu i parametrów. Zależy ono od operacji, sprzętu, konfiguracji biblioteki oraz kosztu wywołania przez wrapper.

Nie trzeba rezygnować z Pythona ani notebooka. Wrapper, czyli nakładka językowa, przekazuje wywołania z Pythona do MCL. Studenci przygotowali dwa takie projekty: piotrszyma/mcl-python oraz Fadion96/mcl-python. Pozwalają eksperymentować z protokołami, zachowując opis i analizę wyników w notebooku. Pozostałe projekty MCL w Teaching obejmują także Rust i serwer testowy Node.js. W przeglądarce można korzystać z MCL WebAssembly, na którym działają demonstratory kursu.

Przed rozpoczęciem sprawdź konfigurację. Wrappery wymagają odpowiedniej instalacji MCL. Sprawdź wersję interfejsu, obsługiwaną krzywą i system operacyjny, a następnie uruchom testy danego repozytorium. Dokumentacja projektu Fadion96 deklaruje obsługę Linuksa i pokazuje inicjalizację BLS12-381. Starszy wrapper może wymagać dopasowania do nowszego MCL. Nie zakładaj zgodności tylko na podstawie nazwy pakietu. W raporcie podaj wybraną wersję wrappera i MCL.

Porównanie tego samego schematu

Do porównania przygotowują L3, L4 i L9. Najpierw sprawdź poprawność obu realizacji. Następnie wykonaj te same serie obliczeń i oddziel pomiar od wyświetlania wyników.

  • Przenieś jeden działający protokół z notebooka. Zapisz odpowiedniki działań py_ecc w MCL oraz granice wejść i wyjść.
  • Powtórz testy poprawności, uszkodzenia transkryptu i odzyskania sekretu przy resecie nonce. Sprawdź, czy oba programy realizują identyczny wariant schematu.
  • Oddziel koszt operacji grupowych od haszowania, kodowania, inicjalizacji WASM i obsługi interfejsu. Skorzystaj z pomiaru MCL. Zastosuj metodologię z L9, ale nie zestawiaj małej grupy modulo 23 z BLS12-381 jako równoważnych konfiguracji.
  • Porównuj bajty tylko przy zgodnych profilach kodowania i haszowania. Szybszy wynik nie dowodzi większego bezpieczeństwa. Wolniejsza implementacja może być dogodniejsza do śledzenia obliczeń.

Kontrola implementacji i projekt do wyboru

Przed oddaniem wybranego zadania sprawdź:

  • Typy: skalar, punkt G1G_1, punkt G2G_2, element GTG_T i bajty nie są zamienne.
  • Losowość: źródło kryptograficzne, zakres i reguły ponownego użycia.
  • Kodowanie: jednoznaczny transkrypt, etykiety dziedzin i obsługa UTF-8.
  • Weryfikacja podpisu: korzysta wyłącznie z jawnego wejścia i parametrów. Sprawdzanie MAC wymaga natomiast wspólnego tajnego klucza. Każda rola otrzymuje dokładnie dane określone w interfejsie badanego schematu.
  • Błędy: zmienione wejścia są odrzucane, a poprzedni wynik nie pozostaje oznaczony jako aktualny.
  • Wnioski: wynik testu, benchmark i twierdzenie o bezpieczeństwie są rozdzielone.
  • Powtarzalność: dołącz notebook, wersje pakietów i wynik uruchomienia od pierwszej komórki w świeżym kernelu. Nie polegaj na ręcznej kolejności wykonywania komórek.

Projekt do samodzielnego rozwinięcia może obejmować odtworzenie wybranego demonstratora, testy modelu ujawnień, porównanie reprezentacji lub kontrolę dowodu. Można połączyć go z jedną ścieżką badawczą. Dobór zakresu, ewentualnej pracy magisterskiej i dalszej współpracy wymaga indywidualnego ustalenia.