Laboratorium 4
Zadania laboratoryjne dla studentów 7 semestru IT - ocena 3.0

Poziom: ocena 3.0 - podstawy kryptografii asymetrycznej i podpisów cyfrowych

Zestaw 10 praktycznych zadań laboratoryjnych do wykonania w trakcie zajęć (90–100 minut).
Kierunek: Informatyka, semestr 7, przedmiot: Kryptologia.
Podstawa materiałowa: wykład część 4 (kryptografia asymetryczna - RSA, ECC, Diffie-Hellman i podpisy cyfrowe).

Wskazówki dla studenta i zasady realizacji:

  • Zadania na ocenę 3.0 skupiają się na praktycznym zrozumieniu mechanizmów współczesnej kryptografii asymetrycznej: struktury kluczy RSA i ECC, algorytmów uzgadniania kluczy Diffiego-Hellmana (klasycznego DH i ECDH/X25519), schematów dopełnienia (PKCS#1 v1.5, OAEP, PSS), generowania i weryfikacji podpisów cyfrowych (RSA, ECDSA, Ed25519) oraz modelu szyfrowania hybrydowego.
  • Wszystkie zadania są w pełni wykonalne bez praw administratora na systemie Windows - wymagają wyłącznie nowoczesnej przeglądarki internetowej i darmowych narzędzi online (CyberChef) oraz konsoli linuksowej z pakietem OpenSSL w emulatorze JSLinux Alpine.
  • Każde zadanie realizowane jest w czasie 90–100 minut w trakcie zajęć laboratoryjnych.
  • Wymagania formalne sprawozdania laboratoryjnego:
    • Strona tytułowa zawierająca: imię i nazwisko studenta, numer albumu, kierunek, semestr, grupę laboratoryjną, rok akademicki, numer i temat laboratorium, numer oraz nazwę realizowanego zadania, deklarowaną ocenę (3.0).
    • Opis konfiguracji środowiska badawczego, adresów serwisów WWW oraz wykorzystanych poleceń.
    • Szczegółowy opis wykonanych czynności, uzasadnienie wyboru narzędzi, zrzuty ekranu oraz wklejone fragmenty danych wejściowych i wyjściowych dokumentujące rzetelne wykonanie pracy.
    • Struktura raportu: spis treści, spis ilustracji (z numerami i podpisami), spis tabel (z numerami i podpisami) oraz wykaz źródeł literaturowych i internetowych.
Kryptologia
lab 4 - 3.0
Spis
Spis zadań laboratoryjnych na ocenę 3.0
01/10
Zadanie 1. Generowanie par kluczy RSA i analiza ich struktury ASN.1 oraz formatu PEM w OpenSSL i CyberChef
🖥️ Wymagane środowisko:
System: Windows (bez praw administratora) + JSLinux Alpine w przeglądarce
Oprogramowanie: przeglądarka + CyberChef + OpenSSL
Podstawa wykładowa: Część 4 - slajdy 6, 7, 37: historia RSA, generowanie kluczy p i q, moduł n = p*q, wykładnik publiczny e=65537, wykładnik prywatny d, struktura formatów PEM i ASN.1.

Cel

Celem zadania jest praktyczne zapoznanie się z procedurą generowania asymetrycznych par kluczy algorytmu RSA o długości 2048 oraz 4096 bitów. Student bada wewnętrzną strukturę matematyczną klucza zapisanego w formacie PEM, dekoduje strukturę ASN.1 DER za pomocą narzędzi OpenSSL oraz CyberChef i identyfikuje składowe n, e, d, p, q oraz wykładniki CRT.

Scenariusz – opis

Zadanie rozpoczynasz od otwarcia konsoli linuksowej JSLinux Alpine z biblioteką OpenSSL oraz serwisu CyberChef w przeglądarce internetowej. Kryptografia asymetryczna opiera się na parze powiązanych matematycznie kluczy, z których jeden jest udostępniany publicznie, a drugi musi pozostać ściśle tajny. W algorytmie RSA klucz opiera się na iloczynie dwóch wielkich liczb pierwszych p oraz q, które tworzą moduł publiczny n. Standardowo jako wykładnik publiczny e stosuje się liczbę pierwszą Fermata F4 równą 65537, która umożliwia efektywne obliczanie potęg modularnych. Klucz prywatny d jest odwrotnością modularną wykładnika e względem funkcji Eulera fi(n), co wynika z rozszerzonego algorytmu Euklidesa. W systemach produkcyjnych klucze kryptograficzne są kodowane w standardzie ASN.1 z serializacją DER i opakowywane w czytelny format PEM z nagłówkami BASE64.

Co ma wykonać student / grupa

W terminalu JSLinux wykonujesz polecenie generowania klucza prywatnego RSA o długości 2048 bitów za pomocą nowoczesnego polecenia openssl genpkey. Zapisujesz wygenerowany klucz do pliku klucz_prywatny_2048.pem i wyświetlasz jego tekstową reprezentację za pomocą edytora lub polecenia cat. Zauważasz charakterystyczne nagłówki BEGIN PRIVATE KEY oraz zakodowany blok znaków alfanumerycznych w formacie Base64. Wyodrębniasz powiązany klucz publiczny za pomocą polecenia openssl pkey z parametrem -pubout do pliku klucz_publiczny_2048.pem.

Przeprowadzasz szczegółową inspekcję klucza prywatnego poleceniem openssl rsa z flagą -text i -noout, odczytując wartości szesnastkowe wszystkich parametrów. Identyfikujesz w wyjściu moduł n o długości 2048 bitów, publiczny wykładnik e, tajny wykładnik d oraz składowe liczby pierwsze p i q. Odnotowujesz także obecność współczynników dP, dQ i qInv służących do przyspieszenia deszyfrowania na mocy chińskiego twierdzenia o resztach CRT. Kopiujesz zawartość pliku klucz_prywatny_2048.pem i wklejasz go do panelu wejściowego serwisu CyberChef.

W CyberChef dodajesz operację Parse ASN.1 i analizujesz drzewo sekwencji ASN.1 opisane standardem PKCS#8 i PKCS#1. Weryfikujesz, że struktura ASN.1 klucza publicznego zawiera wyłącznie moduł oraz wykładnik publiczny, nie zdradzając parametrów tajnych. Powtarzasz generowanie dla klucza o długości 4096 bitów i mierzysz czas operacji poleceniem time w terminalu JSLinux, raportując czas wyłącznie względnie (stosunek 4096 vs 2048 na tym samym hoście, bez porównań między studentami). Jeżeli emulator JSLinux zamula przy RSA-4096 i generowanie grozi przekroczeniem limitu zajęć, stosujesz awaryjny wariant 3072 bitów (openssl genpkey -pkeyopt rsa_keygen_bits:3072) i odnotowujesz to w sprawozdaniu.

Zabezpieczasz klucz prywatny hasłem z wykorzystaniem algorytmu AES-256 poleceniem openssl rsa -aes256 i obserwujesz zmianę nagłówka PEM. Zapisujesz wszystkie zrzuty ekranu, wygenerowane fragmenty ASN.1 oraz heksadecymalne postacie parametrów modularnych.

Sporządzasz tabelę zestawiającą parametry klucza 2048-bitowego oraz 4096-bitowego wraz z liczbą bajtów ich reprezentacji DER. Weryfikujesz spójność wszystkich zebranych materiałów i przygotowujesz dokumentację do sprawozdania.

Przykładowe kroki do wykonania jako sugestia

  1. Otwórz w przeglądarce terminal JSLinux Alpine oraz serwis CyberChef.
  2. W konsoli JSLinux wygeneruj klucz prywatny RSA 2048-bit: openssl genpkey -algorithm RSA -out rsa_priv_2048.pem -pkeyopt rsa_keygen_bits:2048.
  3. Wyświetl zawartość pliku klucza poleceniem: cat rsa_priv_2048.pem.
  4. Wyeksportuj klucz publiczny: openssl pkey -in rsa_priv_2048.pem -pubout -out rsa_pub_2048.pem.
  5. Wyświetl zawartość wygenerowanego klucza publicznego: cat rsa_pub_2048.pem.
  6. Wykonaj pełną inspekcję składowych klucza prywatnego: openssl rsa -in rsa_priv_2048.pem -text -noout.
  7. Zanotuj wartości modułu n, wykładnika e (0x10001), wykładnika d oraz czynników pierwszych prime1 i prime2.
  8. Wykonaj inspekcję klucza publicznego: openssl rsa -pubin -in rsa_pub_2048.pem -text -noout.
  9. Przekonwertuj klucz PEM do formatu binarnego DER: openssl rsa -in rsa_priv_2048.pem -outform DER -out rsa_priv.der.
  10. Zbadaj strukturę ASN.1 w konsoli poleceniem: openssl asn1parse -in rsa_priv_2048.pem.
  11. Wklej zawartość pliku rsa_priv_2048.pem do narzędzia CyberChef i użyj operacji Parse ASN.1.
  12. Wygeneruj klucz o długości 4096 bitów mierząc czas: time openssl genpkey -algorithm RSA -out rsa_priv_4096.pem -pkeyopt rsa_keygen_bits:4096 (raportuj tylko czas względny 4096 vs 2048 na tym samym hoście; awaryjnie, gdy emulator zamula, użyj 3072 bitów: -pkeyopt rsa_keygen_bits:3072).
  13. Zabezpiecz klucz prywatny hasłem: openssl rsa -in rsa_priv_2048.pem -aes256 -out rsa_priv_enc.pem.
  14. Sprawdź nagłówki zaszyfrowanego pliku PEM poleceniem cat rsa_priv_enc.pem i zidentyfikuj deklarację algorytmu szyfrowania klucza.
  15. Wykonaj zrzuty ekranu drzewa ASN.1 w CyberChef oraz wyjścia tekstowego openssl rsa -text.
  16. Sporządź tabelę porównawczą rozmiarów kluczy 2048 i 4096 bitów w formatach PEM i DER oraz czasów ich generowania.

Kontrola zaliczenia (checklist):

  1. Zachowano artefakt: klucze RSA-2048 i RSA-4096 (.pem) z logiem generowania, wyodrębniony klucz publiczny oraz dekod ASN.1 (openssl rsa/asn1parse + CyberChef) ze wskazaniem n,e,d,p,q i CRT.
  2. Dołączono 2–3 zrzuty z podpisami: generowanie w JSLinux, struktura ASN.1 oraz pomiar czasu generowania 2048 vs 4096 na tym samym hoście (względnie).
  3. Opisano w 2–3 zdaniach wybór narzędzi (OpenSSL do generowania, CyberChef do wizualizacji ASN.1/PEM) i formaty PKCS#1 vs PKCS#8.
  4. Zapisano wnioski (3–5 zdań): rola n,e,d,p,q, Base64 vs DER, ochrona klucza hasłem, narzut 4096 (awaryjnie 3072).

Wariant offline (fallback): Brak sieci/JSLinux: lokalny OpenSSL (Git-Bash/WSL) na plikach ze startera; CyberChef/kalkulatory zastąp opisem z cache i logiem openssl (rsa/ec/pkeyutl/derive/verify); dołącz pliki .pem/.der i zrzuty.

Sugerowane wnioski i podsumowanie - co student ma osiągnąć

Sprawozdanie z realizacji zadania musi zawierać następujące kluczowe wnioski i osiągnięcia:

  • Zrozumienie matematycznej budowy pary kluczy RSA: roli modułu n, wykładnika e, wykładnika d oraz liczb pierwszych p i q.
  • Znajomość struktury formatu PEM (Base64) oraz binarnego formatu ASN.1 DER (PKCS#1 i PKCS#8).
  • Praktyczna umiejętność bezpiecznego wyodrębniania klucza publicznego oraz zabezpieczania klucza prywatnego szyfrem symetrycznym.
  • Świadomość narzutu wydajnościowego generowania kluczy o długości 4096 bitów w stosunku do standardu 2048 bitów (czasy raportowane wyłącznie względnie na tym samym hoście; wariant awaryjny 3072 bity).
Zadanie 1 - ilustracja
02/10
Zadanie 2. Szyfrowanie i deszyfrowanie asymetryczne RSA oraz analiza dopełnienia PKCS#1 v1.5 i OAEP
🖥️ Wymagane środowisko:
System: Windows (bez praw administratora) + JSLinux Alpine w przeglądarce
Oprogramowanie: przeglądarka + CyberChef + OpenSSL
Podstawa wykładowa: Część 4 - slajdy 8, 10, 12: operacje c = m^e mod n i m = c^d mod n, ograniczenie długości wiadomości m < n, rola paddingu, podatność braku paddingu, standardy PKCS#1 v1.5 oraz OAEP.

Cel

Celem zadania jest praktyczne zbadanie procesu szyfrowania i deszyfrowania asymetrycznego RSA przy użyciu narzędzia OpenSSL pkeyutl oraz serwisu CyberChef. Student bada wpływ schematów dopełnienia (PKCS#1 v1.5 oraz OAEP ze skrótem SHA-256) na postać szyfrogramu oraz wyznacza maksymalny dopuszczalny rozmiar tekstu jawnego dla zadanego modułu n.

Scenariusz – opis

W tym laboratorium przeanalizujesz proces szyfrowania asymetrycznego za pomocą klucza publicznego RSA i deszyfrowania kluczem prywatnym. Podstawowa formuła matematyczna szyfruje liczbę całkowitą m reprezentującą wiadomość według wzoru c = m^e mod n. W praktyce surowe potęgowanie bez dopełnienia jest skrajnie niebezpieczne, gdyż jest deterministyczne i podatne na ataki algebraiczne. Z tego powodu każda wiadomość musi zostać uzupełniona losowym paddingiem przed wykonaniem operacji modularnej. Historyczny standard PKCS#1 v1.5 wprowadza dopełnienie losowymi bajtami niezerowymi, jednak okazał się podatny na ataki wyroczni paddingu. Nowoczesnym i rekomendowanym standardem jest OAEP (Optimal Asymmetric Encryption Padding), który łączy maskowanie losowe z funkcją skrótu.

Co ma wykonać student / grupa

W emulatorze JSLinux przygotowujesz parę kluczy RSA o długości 2048 bitów wygenerowaną w zadaniu poprzednim. Tworzysz krótki plik tekstowy zawierający poufną wiadomość o długości kilkunastu znaków, na przykład haslo_tajne_lab4. Szyfrujesz plik kluczem publicznym za pomocą narzędzia openssl pkeyutl z domyślnym paddingiem PKCS#1 v1.5 i zapisujesz wynik do pliku binarnego. Sprawdzasz rozmiar pliku wynikowego poleceniem ls-l i stwierdzasz, że wynosi on dokładnie 256 bajtów, co odpowiada rozmiarowi 2048-bitowego modułu n.

Wykonujesz szyfrowanie tej samej wiadomości po raz drugi i porównujesz oba pliki za pomocą polecenia cmp lub sum kontrolnych sha256sum. Zauważasz, że szyfrogramy różnią się całkowicie, co potwierdza losowy charakter paddingu PKCS#1 v1.5 i brak determinizmu. Odszyfrowujesz plik za pomocą klucza prywatnego poleceniem openssl pkeyutl -decrypt i sprawdzasz zgodność odzyskanego tekstu z oryginałem.

Następnie wykonujesz szyfrowanie z wykorzystaniem bezpiecznego schematu OAEP z parametrem rsa_padding_mode:oaep oraz skrótem SHA-256. Badany schemat OAEP ze skrótem SHA-256 rezerwuje 2*hLen + 2 bajtów na nagłówki, co przy skrócie 32-bajtowym daje narzut 66 bajtów. Obliczasz maksymalny rozmiar wiadomości: dla modułu 2048 bitów (256 bajtów) wynosi on 256 - 66 = 190 bajtów. Tworzysz plik testowy o długości 190 bajtów i z powodzeniem go szyfrujesz, a następnie plik o długości 191 bajtów, rejestrując błąd narzędzia OpenSSL.

W serwisie CyberChef konfigurujesz operację RSA Encrypt oraz RSA Decrypt, wprowadzając wygenerowane klucze PEM i testując padding OAEP. Wykonujesz próbę odszyfrowania pliku z uszkodzonym jednym bajtem szyfrogramu i analizujesz zgłoszony błąd integralności paddingu. Sporządzasz zestawienie tabelaryczne narzutów bajtowych dla braku paddingu, PKCS#1 v1.5 oraz OAEP z SHA-1 i SHA-256.

Formułujesz twardy wniosek normatywny do raportu: nowe systemy szyfrują wyłącznie OAEP, a PKCS#1 v1.5 służy tylko do odczytu starych danych (por. atak Bleichenbachera, poziom 5.0/zad. 4). Zapisujesz wszystkie polecenia, zrzuty ekranu i sformułowane wnioski w notatkach laboratoryjnych.

Przykładowe kroki do wykonania jako sugestia

  1. Przygotuj w JSLinux klucz prywatny rsa_priv_2048.pem oraz publiczny rsa_pub_2048.pem.
  2. Utwórz plik z testową wiadomością: echo -n 'Poufna wiadomosc laboratoryjna' > msg.txt.
  3. Zaszyfruj wiadomość z paddingiem PKCS#1 v1.5: openssl pkeyutl -encrypt -pubin -inkey rsa_pub_2048.pem -in msg.txt -out msg_pkcs1.enc.
  4. Sprawdź rozmiar szyfrogramu: ls -l msg_pkcs1.enc (powinno być dokładnie 256 bajtów).
  5. Zaszyfruj tę samą wiadomość ponownie do pliku msg_pkcs1_kopia.enc i porównaj sumy: sha256sum msg_pkcs1*.enc.
  6. Odszyfruj plik kluczem prywatnym: openssl pkeyutl -decrypt -inkey rsa_priv_2048.pem -in msg_pkcs1.enc -out msg_dec.txt.
  7. Zweryfikuj zgodność odzyskanego tekstu: diff msg.txt msg_dec.txt.
  8. Zaszyfruj wiadomość z użyciem OAEP i SHA-256: openssl pkeyutl -encrypt -pubin -inkey rsa_pub_2048.pem -in msg.txt -out msg_oaep.enc -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256.
  9. Odszyfruj szyfrogram OAEP: openssl pkeyutl -decrypt -inkey rsa_priv_2048.pem -in msg_oaep.enc -out msg_oaep_dec.txt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256.
  10. Wygeneruj plik o dopuszczalnym rozmiarze granicznym 190 bajtów: head -c 190 /dev/urandom > msg_190.bin.
  11. Zaszyfruj plik 190-bajtowy w schemacie OAEP SHA-256 i potwierdź sukces operacji.
  12. Wygeneruj plik o rozmiarze 191 bajtów: head -c 191 /dev/urandom > msg_191.bin.
  13. Spróbuj zaszyfrować plik 191-bajtowy i zarejestruj komunikat błędu: data too large for key size.
  14. W CyberChef załaduj klucz publiczny i wykonaj operację RSA Encrypt w trybie OAEP.
  15. Zmodyfikuj 1 bajt w pliku msg_oaep.enc za pomocą edytora lub polecenia sed/dd i spróbuj go odszyfrować.
  16. Zanotuj komunikat błędu deszyfrowania uszkodzonego szyfrogramu.

Kontrola zaliczenia (checklist):

  1. Zachowano artefakt: szyfrogram RSA dla ustalonego tekstu w obu paddingach (PKCS#1 v1.5 i OAEP-SHA256) + log dwóch szyfrowań tego samego tekstu (różne szyfrogramy = losowość) + udane deszyfrowanie.
  2. Dołączono 2–3 zrzuty z podpisami: komendy openssl pkeyutl -encrypt/-decrypt dla obu paddingów oraz porównanie szyfrogramów (hex).
  3. Opisano w 2–3 zdaniach wybór narzędzi i wyliczony limit plaintext dla OAEP (k − 2h − 2).
  4. Zapisano wnioski (3–5 zdań): stała długość = moduł, losowość paddingu vs determinizm, detekcja uszkodzeń, norma: nowe systemy tylko OAEP (v1.5 do odczytu).

Wariant offline (fallback): Brak sieci/JSLinux: lokalny OpenSSL (Git-Bash/WSL) na plikach ze startera; CyberChef/kalkulatory zastąp opisem z cache i logiem openssl (rsa/ec/pkeyutl/derive/verify); dołącz pliki .pem/.der i zrzuty.

Sugerowane wnioski i podsumowanie - co student ma osiągnąć

Sprawozdanie z realizacji zadania musi zawierać następujące kluczowe wnioski i osiągnięcia:

  • Zrozumienie, dlaczego szyfrowanie asymetryczne RSA produkuje szyfrogram o stałej długości równej długości modułu n.
  • Praktyczna weryfikacja losowości paddingu PKCS#1 v1.5 oraz standardu OAEP uniemożliwiającej ataki deterministyczne.
  • Precyzyjne wyznaczenie limitu rozmiaru tekstu jawnego w schemacie OAEP w zależności od rozmiaru modułu i funkcji skrótu.
  • Wykazanie mechanizmu detekcji uszkodzenia szyfrogramu przy weryfikacji struktury paddingu podczas deszyfrowania.
  • Zasada normatywna: nowe systemy tylko OAEP, PKCS#1 v1.5 wyłącznie do odczytu danych historycznych (por. 5.0/zad. 4 Bleichenbacher).
Zadanie 2 - ilustracja
03/10
Zadanie 3. Podstawowa wymiana kluczy Diffiego-Hellmana (DH) w narzędziu konsolowym OpenSSL i kalkulatorze WWW
🖥️ Wymagane środowisko:
System: Windows (bez praw administratora) + JSLinux Alpine w przeglądarce
Oprogramowanie: przeglądarka + OpenSSL + Python 3
Podstawa wykładowa: Część 4 - slajdy 13, 14, 15, 49: problem bezpiecznej wymiany klucza przez podsłuchiwany kanał, grupa cykliczna Z_p^*, generator g, klucze prywatne a i b, klucze publiczne A i B, uzgadnianie sekretu K.

Cel

Celem zadania jest praktyczne przećwiczenie klasycznego protokołu uzgadniania kluczy Diffiego-Hellmana (DH). Student bada strukturę parametrów grupy (liczba pierwsza p oraz generator g), generuje klucze asymetryczne dla dwóch niezależnych stron (Alice i Bob) oraz oblicza wspólny sekret sesyjny w narzędziu OpenSSL i prostym kalkulatorze modularnym online.

Scenariusz – opis

Protokół Diffiego-Hellmana opublikowany w 1976 roku zrewolucjonizował kryptografię, umożliwiając uzgodnienie wspólnego sekretu przez publiczny kanał. Bezpieczeństwo protokołu opiera się na trudności obliczeniowej problemu logarytmu dyskretnego DLP w ciele liczb pierwszych Z_p^*. Strony przed rozpoczęciem komunikacji muszą ustalić wspólne parametry dziedzinowe: wielką liczbę pierwszą p oraz generator grupy g. Każda ze stron losuje swój prywatny wykładnik: Alice wybiera tajną wartość a, natomiast Bob wybiera tajną wartość b. Następnie strony obliczają swoje publiczne wykładniki: Alice wysyła A = g^a mod p, a Bob przesyła B = g^b mod p. Obie strony są w stanie niezależnie obliczyć ten sam wspólny sekret: K = B^a mod p = A^b mod p = g^(a*b) mod p.

Co ma wykonać student / grupa

Zadanie rozpoczynasz w emulatorze JSLinux Alpine od wygenerowania parametrów grupy Diffiego-Hellmana o długości 2048 bitów. Jako plan B (gdy genparam w JSLinux trwa kilkanaście minut) używasz gotowych parametrów RFC 3526 MODP-2048 i obowiązkowo raportujesz zmierzony czas generowania, aby nie zjadać całych zajęć. Używasz polecenia openssl genpkey z parametrem -genparam oraz algorytmem DH i zapisujesz wynik do pliku dh_parametry.pem. Dokonujesz inspekcji parametrów grupy za pomocą openssl pkeyparam -text, odczytując wartość dużej liczby pierwszej p oraz generatora g = 2.

Na podstawie wygenerowanych parametrów tworzysz parę kluczy dla Alice poleceniem openssl genpkey i zapisujesz do alice_priv.pem. Wyodrębniasz klucz publiczny Alice do pliku alice_pub.pem za pomocą openssl pkey z flagą -pubout. W analogiczny sposób generujesz niezależną parę kluczy dla Boba: bob_priv.pem oraz bob_pub.pem. Symulujesz wymianę kluczy przez publiczny kanał i przystępujesz do fazy derywacji wspólnego sekretu poleceniem openssl pkeyutl -derive.

Alice oblicza sekret wykorzystując swój klucz prywatny alice_priv.pem oraz otrzymany klucz publiczny Boba bob_pub.pem. Bob oblicza sekret wykorzystując swój klucz prywatny bob_priv.pem oraz otrzymany klucz publiczny Alice alice_pub.pem. Zapisujesz oba uzyskane pliki binarne sekret_alice.bin oraz sekret_bob.bin i porównujesz ich sumy kontrolne sha256sum. Stwierdzasz całkowitą identyczność obu wyznaczonych sekretów bez konieczności przesyłania tajnych wykładników a i b przez sieć.

Przechodzisz do internetowego kalkulatora modularnego lub prostego skryptu i powtarzasz procedurę na miniaturowych parametrach: p = 23, g = 5, a = 6, b = 15. Sprawdzasz obliczenia ręcznie: A = 5^6 mod 23 = 8, B = 5^15 mod 23 = 19, K = 19^6 mod 23 = 2 oraz K = 8^15 mod 23 = 2. Zapisujesz wyniki w postaci tabeli prezentującej parametry rzeczywiste 2048-bitowe oraz miniaturowe dydaktyczne. Formułujesz podsumowanie opisujące odporność podsłuchiwacza biernego (Eve) na poznanie sekretu K przy znajomości jedynie p, g, A i B.

Przykładowe kroki do wykonania jako sugestia

  1. Uruchom konsolę JSLinux Alpine w oknie przeglądarki.
  2. Wygeneruj parametry grupy DH 2048-bit: openssl genpkey -genparam -algorithm DH -out dh_params.pem -pkeyopt dh_paramgen_prime_len:2048 (mierz czas time; plan B przy zamulaniu: użyj gotowych parametrów RFC 3526 MODP-2048).
  3. Wyświetl strukturę parametrów DH: openssl pkeyparam -in dh_params.pem -text -noout.
  4. Zidentyfikuj moduł p (liczba pierwsza) oraz generator g (wartość 2).
  5. Wygeneruj parę kluczy dla Alice: openssl genpkey -paramfile dh_params.pem -out alice_key.pem.
  6. Wyodrębnij klucz publiczny Alice: openssl pkey -in alice_key.pem -pubout -out alice_pub.pem.
  7. Wygeneruj parę kluczy dla Boba: openssl genpkey -paramfile dh_params.pem -out bob_key.pem.
  8. Wyodrębnij klucz publiczny Boba: openssl pkey -in bob_key.pem -pubout -out bob_pub.pem.
  9. Oblicz wspólny sekret po stronie Alice: openssl pkeyutl -derive -inkey alice_key.pem -peerkey bob_pub.pem -out secret_alice.bin.
  10. Oblicz wspólny sekret po stronie Boba: openssl pkeyutl -derive -inkey bob_key.pem -peerkey alice_pub.pem -out secret_bob.bin.
  11. Porównaj sumy SHA-256 obu plików: sha256sum secret_alice.bin secret_bob.bin.
  12. Zbadaj długość wyznaczonego sekretu: ls -l secret_*.bin (256 bajtów odpowiadające 2048 bitom).
  13. Otwórz kalkulator modularny online lub konsolę Pythona w JSLinux: python3.
  14. Wykonaj miniaturowy test DH: p=23; g=5; a=6; b=15; A = pow(g, a, p); B = pow(g, b, p); Ka = pow(B, a, p); Kb = pow(A, b, p); print(A, B, Ka, Kb).
  15. Potwierdź zgodność wartości Ka i Kb równych 2.
  16. Wykonaj zrzuty ekranu poleceń konsoli oraz tabeli parametrów do sprawozdania.

Kontrola zaliczenia (checklist):

  1. Zachowano artefakt: parametry grupy DH (p,g), klucze Alice/Boba oraz obie derywacje identycznego sekretu K z logiem openssl (genpkey/derive) i kalkulatora.
  2. Dołączono 2–3 zrzuty z podpisami: generowanie parametrów, wymiana kluczy publicznych, porównanie sekretów (cmp/hash).
  3. Opisano w 2–3 zdaniach wybór narzędzi (OpenSSL do protokołu, kalkulator do ilustracji potęgowania mod) i relację długości p vs sekretu.
  4. Zapisano wnioski (3–5 zdań): potęgowanie modularne, sekret bez przesyłu, podsłuch p,g,A,B nie daje K bez DLP.

Wariant offline (fallback): Brak sieci/JSLinux: lokalny OpenSSL (Git-Bash/WSL) na plikach ze startera; CyberChef/kalkulatory zastąp opisem z cache i logiem openssl (rsa/ec/pkeyutl/derive/verify); dołącz pliki .pem/.der i zrzuty.

Sugerowane wnioski i podsumowanie - co student ma osiągnąć

Sprawozdanie z realizacji zadania musi zawierać następujące kluczowe wnioski i osiągnięcia:

  • Zrozumienie matematycznej zasady działania protokołu Diffiego-Hellmana opartego na potęgowaniu modularnym.
  • Praktyczna umiejętność generowania parametrów grupy, kluczy stron oraz derywacji wspólnego sekretu w OpenSSL.
  • Dowód na to, że pasywny podsłuchiwacz znający wartości p, g, A, B nie jest w stanie wyznaczyć K bez rozwiązania DLP.
  • Zrozumienie relacji pomiędzy długością liczby pierwszej p a długością wynikowego sekretu sesyjnego.
Zadanie 3 - ilustracja
04/10
Zadanie 4. Podatność protokołu Diffiego-Hellmana na atak Man-in-the-Middle (MitM) przy braku uwierzytelnienia
🖥️ Wymagane środowisko:
System: Windows (bez praw administratora) + JSLinux Alpine w przeglądarce
Oprogramowanie: przeglądarka + OpenSSL
Podstawa wykładowa: Część 4 - slajdy 14, 16: brak uwierzytelnienia tożsamości w klasycznym DH, aktywny atak pośrednika (Man-in-the-Middle), rola podpisów cyfrowych i certyfikatów w zapobieganiu MitM.

Cel

Celem zadania jest praktyczne zademonstrowanie fundamentalnej luki protokołu Diffiego-Hellmana, jaką jest podatność na atak Man-in-the-Middle (MitM) przy braku uwierzytelnienia stron. Student symuluje trzech uczestników komunikacji (Alice, Bob oraz aktywny napastnik Mallory) i dowodzi, że napastnik może podsłuchiwać i modyfikować cały szyfrowany ruch.

Scenariusz – opis

Klasyczny protokół Diffiego-Hellmana zapewnia poufność wyłącznie przed pasywnym obserwatorem kanału komunikacyjnego. Zasadniczym problemem protokołu jest całkowity brak uwierzytelnienia nadawcy klucza publicznego. Gdy w kanale pojawi się aktywny adwersarz Mallory, może przechwycić klucze publiczne Alice i Boba. Mallory generuje własną parę kluczy DH i podstawia swój klucz publiczny M w miejsce kluczy prawowitych uczestników. W rezultacie Alice uzgadnia wspólny klucz z Mallorym, a Bob uzgadnia zupełnie inny wspólny klucz z Mallorym. Mallory staje się pośrednikiem zdolnym do odszyfrowania każdej wiadomości, jej potajemnej modyfikacji i ponownego zaszyfrowania.

Co ma wykonać student / grupa

W terminalu JSLinux Alpine przygotowujesz wspólne parametry grupy DH o długości 2048 bitów zapisane w pliku dh_params.pem. Generujesz klucz prywatny i publiczny Alice (alice_key.pem, alice_pub.pem) oraz Boba (bob_key.pem, bob_pub.pem).

Następnie tworzysz klucz Mallory'ego reprezentujący stację atakującą: mallory_key.pem oraz mallory_pub.pem. Symulujesz przejęcie ruchu: Alice zamiast klucza Boba otrzymuje klucz publiczny mallory_pub.pem. Bob zamiast klucza publicznego Alice otrzymuje klucz publiczny mallory_pub.pem. Wykonujesz derywację sekretu po stronie Alice: poleceniem openssl pkeyutl -derive uzgadnia ona klucz k_alice_mallory.bin.

Mallory derywuje ten sam klucz z kluczem publicznym Alice: poleceniem OpenSSL uzyskuje identyczny plik k_alice_mallory.bin. W podobny sposób Bob derywuje klucz z kluczem publicznym Mallory'ego: uzyskuje plik k_bob_mallory.bin. Mallory derywuje drugi klucz z kluczem publicznym Boba: uzyskuje identyczny plik k_bob_mallory.bin. Zauważasz, że Alice i Bob są przekonani o nawiązaniu bezpiecznego połączenia, lecz posiadają dwa zupełnie różne klucze sesyjne.

Tworzysz testową wiadomość Alice 'Przelew: 1000 PLN do Boba' i szyfrujesz ją kluczem k_alice_mallory za pomocą opensslenc -aes-256-cbc z losowym IV (openssl rand 16) przekazywanym jawnym kanałem. Odnotowujesz w raporcie, że stałe IV (np. same zera) łamie semantyczne bezpieczeństwo trybu CBC i jest w karcie zabronione. Mallory odszyfrowuje wiadomość za pomocą k_alice_mallory, modyfikuje treść na 'Przelew: 9000 PLN do Mallory' i szyfruje kluczem k_bob_mallory. Bob odbiera szyfrogram, odszyfrowuje go bez błędu swoim kluczem k_bob_mallory i odczytuje sfałszowaną dyspozycję.

Dokumentujesz zrzutami ekranu poszczególne etapy ataku, generowane pliki kluczy oraz sumy kontrolne. Wyjaśniasz w sprawozdaniu, dlaczego nowoczesne protokoły (np. TLS) wymagają cyfrowego podpisywania parametrów DH certyfikatem cyfrowym.

Przykładowe kroki do wykonania jako sugestia

  1. W terminalu JSLinux wygeneruj parametry DH: openssl genpkey -genparam -algorithm DH -out dh_params.pem -pkeyopt dh_paramgen_prime_len:2048.
  2. Wygeneruj klucze Alice: openssl genpkey -paramfile dh_params.pem -out alice_key.pem && openssl pkey -in alice_key.pem -pubout -out alice_pub.pem.
  3. Wygeneruj klucze Boba: openssl genpkey -paramfile dh_params.pem -out bob_key.pem && openssl pkey -in bob_key.pem -pubout -out bob_pub.pem.
  4. Wygeneruj klucze Mallory'ego: openssl genpkey -paramfile dh_params.pem -out mallory_key.pem && openssl pkey -in mallory_key.pem -pubout -out mallory_pub.pem.
  5. Przeprowadź derywację klucza Alice (Alice myśli, że łączy się z Bobem): openssl pkeyutl -derive -inkey alice_key.pem -peerkey mallory_pub.pem -out k_am1.bin.
  6. Przeprowadź derywację Mallory dla połączenia z Alice: openssl pkeyutl -derive -inkey mallory_key.pem -peerkey alice_pub.pem -out k_am2.bin.
  7. Sprawdź tożsamość klucza Alice-Mallory: cmp k_am1.bin k_am2.bin.
  8. Przeprowadź derywację klucza Boba (Bob myśli, że łączy się z Alice): openssl pkeyutl -derive -inkey bob_key.pem -peerkey mallory_pub.pem -out k_bm1.bin.
  9. Przeprowadź derywację Mallory dla połączenia z Bobem: openssl pkeyutl -derive -inkey mallory_key.pem -peerkey bob_pub.pem -out k_bm2.bin.
  10. Sprawdź tożsamość klucza Bob-Mallory: cmp k_bm1.bin k_bm2.bin.
  11. Upewnij się, że klucze obu kanałów są różne: cmp k_am1.bin k_bm1.bin (powinien zgłosić różnicę).
  12. Utwórz wiadomość Alice: echo 'Przelew: 1000 PLN do Boba' > msg_orig.txt.
  13. Wyprowadź 32-bajtowe klucze AES: sha256sum k_am1.bin | cut -d' ' -f1 > k_am.hex && sha256sum k_bm1.bin | cut -d' ' -f1 > k_bm.hex.
  14. Zaszyfruj wiadomość kluczem Alice-Mallory: openssl rand -out iv.bin 16 && openssl enc -aes-256-cbc -in msg_orig.txt -out c_alice.enc -K $(cat k_am.hex) -iv $(xxd -p iv.bin | tr -d '\n') (IV jawny, losowy dla każdego szyfrowania; stałe IV zerowe zabronione).
  15. Jako Mallory odszyfruj wiadomość, zmień treść na sfałszowaną i zaszyfruj kluczem Bob-Mallory.
  16. Jako Bob odszyfruj wiadomość i zarejestruj udaną manipulację bez wykrycia błędu kryptograficznego.

Kontrola zaliczenia (checklist):

  1. Zachowano artefakt: log trzech ról (Alice–MitM–Bob) pokazujący dwa różne sekrety K_AM i K_MB oraz odszyfrowany przez MitM tekst (dowód przełamania poufności).
  2. Dołączono 2–3 zrzuty z podpisami: sesje Alice–MitM i MitM–Bob obok siebie oraz przechwycenie/odszyfrowanie wiadomości.
  3. Opisano w 2–3 zdaniach sposób symulacji atakującego i dlaczego strony nie wykrywają podmiany.
  4. Zapisano wnioski (3–5 zdań): czysty DH bez uwierzytelnienia = dwa tunele, poufność≠tożsamość, obrona: podpis parametrów certyfikatem (TLS).

Wariant offline (fallback): Brak sieci/JSLinux: lokalny OpenSSL (Git-Bash/WSL) na plikach ze startera; CyberChef/kalkulatory zastąp opisem z cache i logiem openssl (rsa/ec/pkeyutl/derive/verify); dołącz pliki .pem/.der i zrzuty.

Sugerowane wnioski i podsumowanie - co student ma osiągnąć

Sprawozdanie z realizacji zadania musi zawierać następujące kluczowe wnioski i osiągnięcia:

  • Empiryczny dowód na podatność czystego protokołu DH na atak pośrednika Man-in-the-Middle.
  • Zrozumienie, że protokoły kryptograficzne muszą zapewniać nie tylko poufność, ale także uwierzytelnienie tożsamości.
  • Wiedza o tym, w jaki sposób napastnik MitM rozdziela jedną sesję na dwa niezależne tunele kryptograficzne.
  • Zrozumienie mechanizmu obrony przed MitM w protokołach SSL/TLS poprzez podpisywanie parametrów DH kluczem certyfikatu X.509.
Zadanie 4 - ilustracja
05/10
Zadanie 5. Generowanie par kluczy i inspekcja parametrów kryptografii krzywych eliptycznych (ECC: P-256 vs Curve25519)
🖥️ Wymagane środowisko:
System: Windows (bez praw administratora) + JSLinux Alpine w przeglądarce
Oprogramowanie: przeglądarka + CyberChef + OpenSSL
Podstawa wykładowa: Część 4 - slajdy 18, 19, 20, 37: kryptografia krzywych eliptycznych, równanie Weierstrassa y^2 = x^3 + ax + b, standardy NIST P-256 (prime256v1) i Curve25519, porównanie długości kluczy ECC vs RSA.

Cel

Celem zadania jest praktyczne zapoznanie się ze strukturą kluczy kryptografii krzywych eliptycznych (ECC). Student porównuje standardowe krzywe Weierstrassa (NIST P-256) z nowoczesnymi krzywymi Montgomery'ego (Curve25519), bada strukturę punktu bazowego G, klucza prywatnego d oraz klucza publicznego Q = d*G za pomocą narzędzi OpenSSL i CyberChef.

Scenariusz – opis

Kryptografia krzywych eliptycznych (ECC) stanowi fundament współczesnych bezpiecznych komunikatorów i protokołów internetowych. Główną zaletą ECC jest oferowanie równoważnego poziomu bezpieczeństwa przy dramatycznie krótszych kluczach niż w przypadku RSA. Przykładowo 256-bitowy klucz na krzywej eliptycznej zapewnia poziom bezpieczeństwa odpowiadający 3072-bitowemu kluczowi RSA. W ECC klucz prywatny d jest po prostu losową liczbą całkowitą z przedziału rzędu grupy punktów. Klucz publiczny Q jest punktem na krzywej o współrzędnych (x, y) powstałym w wyniku operacji wielokrotnego dodawania punktu bazowego Q = d * G. Odwrócenie tej operacji wymaga rozwiązania problemu logarytmu dyskretnego na krzywych eliptycznych (ECDLP), co jest obliczeniowo nieosiągalne.

Co ma wykonać student / grupa

W terminalu JSLinux przeglądasz listę krzywych eliptycznych obsługiwanych przez bibliotekę OpenSSL za pomocą polecenia openssl ecparam -list_curves. Wybierasz najpopularniejszą krzywą standaryzowaną przez NIST: prime256v1 (znaną również jako secp256r1 lub NIST P-256). Generujesz parametry dziedzinowe oraz parę kluczy za pomocą polecenia openssl ecparam z flagami -name prime256v1 i -genkey (ścieżka stara, wyłącznie dla P-256). Zapamiętujesz ramkę narzędziową z karty: stara składnia ecparam/ec tylko dla P-256, nowa składnia genpkey/pkey dla X25519/Ed25519 - bez mieszania obu składni w jednym poleceniu.

Zapisujesz klucz do pliku ec_p256_priv.pem i wyodrębniasz klucz publiczny poleceniem openssl ec -pubout do pliku ec_p256_pub.pem. Wykonujesz pełną tekstową inspekcję klucza poleceniem openssl ec -text -noout i analizujesz strukturę wyjścia. Identyfikujesz 32-bajtową liczbę całkowitą stanowiącą klucz prywatny (priv: 256 bitów) oraz 65-bajtowy nieściśnięty punkt publiczny (pub: 04 || x || y). Odnotowujesz, że prefiks 0x04 oznacza nieskompresowaną postać punktu, po którym następuje 32 bajty współrzędnej x oraz 32 bajty współrzędnej y.

Następnie generujesz klucz oparty o krzywą nowej generacji Curve25519 / X25519 poleceniem openssl genpkey -algorithm X25519. Porównujesz rozmiary plików kluczy P-256 oraz X25519 w formacie binarnym DER za pomocą polecenia ls-l. Zauważasz prostotę klucza X25519, którego surowa reprezentacja klucza publicznego zajmuje zaledwie 32 bajty (256 bitów). W serwisie CyberChef wklejasz klucz publiczny P-256 i dekodujesz go za pomocą operacji Parse ASN.1, sprawdzając identyfikator OID krzywej.

Sporządzasz tabelę porównawczą parametrów RSA-2048, RSA-3072, ECC P-256 oraz Curve25519 (rozmiar klucza prywatnego, publicznego, poziom bezpieczeństwa). Zapisujesz wszystkie zrzuty ekranu konsoli oraz schematy wygenerowanych punktów. Weryfikujesz poprawność zebranych danych i formułujesz wnioski dotyczące efektywności pasmowej i pamięciowej kryptosystemów ECC. Kompletujesz materiały dowodowe do sprawozdania laboratoryjnego.

Przykładowe kroki do wykonania jako sugestia

  1. Otwórz emulator JSLinux Alpine w oknie przeglądarki.
  2. Wyświetl dostępne krzywe eliptyczne: openssl ecparam -list_curves | head -n 25.
  3. Zlokalizuj krzywą prime256v1 (NIST P-256) na liście.
  4. Wygeneruj parę kluczy na krzywej prime256v1: openssl ecparam -name prime256v1 -genkey -noout -out ec_p256_priv.pem.
  5. Wyeksportuj klucz publiczny: openssl ec -in ec_p256_priv.pem -pubout -out ec_p256_pub.pem.
  6. Zbadaj strukturę składowych klucza: openssl ec -in ec_p256_priv.pem -text -noout.
  7. Zanotuj wartość 256-bitowego klucza prywatnego oraz współrzędne x i y punktu publicznego.
  8. Sprawdź klucz publiczny: openssl ec -pubin -in ec_p256_pub.pem -text -noout.
  9. Wygeneruj klucz na nowoczesnej krzywej X25519: openssl genpkey -algorithm X25519 -out x25519_priv.pem.
  10. Wyeksportuj klucz publiczny X25519: openssl pkey -in x25519_priv.pem -pubout -out x25519_pub.pem.
  11. Wyświetl strukturę klucza X25519: openssl pkey -in x25519_priv.pem -text -noout.
  12. Przekonwertuj klucze do formatu DER: openssl ec -in ec_p256_priv.pem -outform DER -out p256.der && openssl pkey -in x25519_priv.pem -outform DER -out x25519.der.
  13. Porównaj rozmiary plików DER: ls -l *.der.
  14. Wklej plik ec_p256_pub.pem do CyberChef i uruchom Parse ASN.1, identyfikując OID krzywej 1.2.840.10045.3.1.7.
  15. Wykonaj zrzuty ekranu parametrów w konsoli JSLinux oraz w CyberChef.
  16. Opracuj tabelę porównawczą długości kluczy ECC w zestawieniu z kluczami RSA pod kątem bitów bezpieczeństwa NIST.

Kontrola zaliczenia (checklist):

  1. Zachowano artefakt: klucze P-256 i X25519 (.pem) z inspekcją parametrów (openssl ecparam/ec), wskazany punkt G oraz format nieskompresowany 0x04|x|y.
  2. Dołączono 2–3 zrzuty z podpisami: generowanie obu krzywych, podgląd klucza publicznego (hex) oraz tabela rozmiarów RSA vs ECC.
  3. Opisano w 2–3 zdaniach wybór narzędzi i różnicę Weierstrass vs Montgomery (polecenia genpkey/ec).
  4. Zapisano wnioski (3–5 zdań): skalar d vs punkt Q, redukcja rozmiaru przy tym samym bezpieczeństwie, komendy dla obu rodzin.

Wariant offline (fallback): Brak sieci/JSLinux: lokalny OpenSSL (Git-Bash/WSL) na plikach ze startera; CyberChef/kalkulatory zastąp opisem z cache i logiem openssl (rsa/ec/pkeyutl/derive/verify); dołącz pliki .pem/.der i zrzuty.

Sugerowane wnioski i podsumowanie - co student ma osiągnąć

Sprawozdanie z realizacji zadania musi zawierać następujące kluczowe wnioski i osiągnięcia:

  • Zrozumienie reprezentacji kluczy ECC: klucz prywatny jako skalar d, klucz publiczny jako punkt Q na krzywej eliptycznej.
  • Identyfikacja nieskompresowanego formatu punktu z prefiksem 0x04 i współrzędnymi x, y.
  • Świadomość ogromnej redukcji rozmiaru kluczy w ECC w stosunku do RSA przy zachowaniu tego samego poziomu bezpieczeństwa.
  • Praktyczna umiejętność posługiwania się poleceniami openssl ecparam, ec oraz genpkey dla krzywych Weierstrassa i Montgomery'ego.
Zadanie 5 - ilustracja
06/10
Zadanie 6. Uzgadnianie klucza w protokole Elliptic Curve Diffie-Hellman (ECDH / X25519) w OpenSSL i CyberChef
🖥️ Wymagane środowisko:
System: Windows (bez praw administratora) + JSLinux Alpine w przeglądarce
Oprogramowanie: przeglądarka + CyberChef + OpenSSL
Podstawa wykładowa: Część 4 - slajdy 14, 20, 39: protokół ECDH (Elliptic Curve Diffie-Hellman), mnożenie punktu przez skalar K = d_A * Q_B = d_B * Q_A, krzywe X25519 i P-256, zastosowanie w TLS 1.3.

Cel

Celem zadania jest praktyczne zbadanie protokołu wymiany kluczy na krzywych eliptycznych ECDH (Elliptic Curve Diffie-Hellman). Student przeprowadza procedurę uzgadniania sekretu sesyjnego na krzywej X25519 oraz P-256 pomiędzy dwiema stronami przy użyciu OpenSSL oraz weryfikuje proces derywacji klucza symetrycznego w narzędziu CyberChef.

Scenariusz – opis

Protokół ECDH stanowi adaptację klasycznego schematu Diffiego-Hellmana do algebry grup punktów na krzywych eliptycznych. Zamiast potęgowania modularnego w ciele liczb pierwszych, uczestnicy wykonują mnożenie skalarne punktu na krzywej. Alice generuje prywatny skalar d_A oraz klucz publiczny Q_A = d_A * G, a Bob generuje d_B oraz Q_B = d_B * G. Wspólny sekret powstaje w wyniku pomnożenia cudzego punktu publicznego przez własny prywatny skalar: K = d_A * Q_B = d_B * Q_A = d_A * d_B * G. Współrzędna x wynikowego punktu K jest następnie przekształcana w symetryczny klucz sesyjny za pomocą funkcji skrótu KDF. Dzięki wyjątkowej szybkości i małym narzutom komunikacyjnym protokół ECDH (w szczególności efemeryczny ECDHE) dominuje w standardzie TLS 1.3.

Co ma wykonać student / grupa

W terminalu JSLinux Alpine generujesz parę kluczy X25519 dla Alice poleceniem openssl genpkey -algorithm X25519 i zapisujesz do alice_x25519.pem. Wyodrębniasz klucz publiczny Alice do pliku alice_xpub.pem za pomocą openssl pkey -pubout.

Następnie tworzysz parę kluczy X25519 dla Boba: bob_x25519.pem oraz bob_xpub.pem. Wykonujesz operację derywacji sekretu po stronie Alice: poleceniem openssl pkeyutl -derive z kluczem prywatnym Alice i publicznym Boba. Zapisujesz wygenerowany sekret binarny do pliku secret_ecdh_alice.bin. Wykonujesz operację derywacji po stronie Boba z kluczem prywatnym Boba i publicznym Alice do pliku secret_ecdh_bob.bin.

Porównujesz oba pliki binarne za pomocą polecenia cmp oraz obliczasz ich skróty sha256sum, dowodząc ich tożsamości. Sprawdzasz rozmiar pliku sekretu i odnotowujesz, że wynosi on dokładnie 32 bajty (256 bitów). Powtarzasz tę samą procedurę dla krzywej NIST P-256 (prime256v1) i badasz wygenerowany 32-bajtowy sekret. Wyprowadzasz z uzyskanego sekretu klucz symetryczny AES-256 za pomocą funkcji skrótu SHA-256 w konsoli (dydaktycznie).

Zapisujesz zastrzeżenie produkcyjne do raportu: sam SHA-256 sekretu to niepełny KDF - produkcyjnie wymagany jest HKDF z solą i info (RFC 5869, por. 5.0/zad. 6 ECIES).

Przechodzisz do serwisu CyberChef i wykorzystujesz wyznaczony klucz do zaszyfrowania i odszyfrowania wiadomości testowej w trybie AES-GCM. Mierzysz czas wykonania 100 operacji derywacji ECDH na X25519 w pętli powłoki i porównujesz go z klasycznym DH-2048. Zauważasz wielokrotnie wyższą wydajność obliczeniową krzywej X25519 w stosunku do arytmetyki modularnej klasycznego DH. Dokumentujesz zrzutami ekranu polecenia OpenSSL, sumy kontrolne oraz recepturę w CyberChef. Przygotowujesz kompletny raport laboratoryjny z opisem wyników i wniosków.

Przykładowe kroki do wykonania jako sugestia

  1. W konsoli JSLinux wygeneruj klucz X25519 Alice: openssl genpkey -algorithm X25519 -out a_xpriv.pem.
  2. Wyeksportuj klucz publiczny Alice: openssl pkey -in a_xpriv.pem -pubout -out a_xpub.pem.
  3. Wygeneruj klucz X25519 Boba: openssl genpkey -algorithm X25519 -out b_xpriv.pem.
  4. Wyeksportuj klucz publiczny Boba: openssl pkey -in b_xpriv.pem -pubout -out b_xpub.pem.
  5. Wykonaj derywację ECDH Alice: openssl pkeyutl -derive -inkey a_xpriv.pem -peerkey b_xpub.pem -out sec_a.bin.
  6. Wykonaj derywację ECDH Boba: openssl pkeyutl -derive -inkey b_xpriv.pem -peerkey a_xpub.pem -out sec_b.bin.
  7. Zweryfikuj zgodność obu sekretów: cmp sec_a.bin sec_b.bin.
  8. Oblicz sumy kontrolne: sha256sum sec_a.bin sec_b.bin.
  9. Wygeneruj klucze na krzywej P-256: openssl ecparam -name prime256v1 -genkey -noout -out a_p256.pem && openssl ec -in a_p256.pem -pubout -out a_p256pub.pem.
  10. Wygeneruj klucze Boba na P-256: openssl ecparam -name prime256v1 -genkey -noout -out b_p256.pem && openssl ec -in b_p256.pem -pubout -out b_p256pub.pem.
  11. Wykonaj derywację na P-256 po obu stronach i porównaj uzyskane sekrety.
  12. Wylicz klucz symetryczny: sha256sum sec_a.bin | cut -d' ' -f1 > aes_key.hex.
  13. Zaszyfruj wiadomość testową wyliczonym kluczem AES: openssl enc -aes-256-cbc -in a_xpub.pem -out test.enc -K $(cat aes_key.hex) -iv 00112233445566778899aabbccddeeff.
  14. Odszyfruj wiadomość za pomocą aes_key.hex i zweryfikuj integralność.
  15. W CyberChef odtwórz deszyfrowanie AES z użyciem uzyskanego klucza szesnastkowego.
  16. Wykonaj zrzuty ekranu z konsoli oraz sporządź tabelę porównawczą ECDH na X25519 i P-256.

Kontrola zaliczenia (checklist):

  1. Zachowano artefakt: log ECDH X25519 i P-256 — obie strony wywodzą identyczny sekret (porównanie hashy), plus HKDF/SHA-256 z sekretu do klucza sesyjnego.
  2. Dołączono 2–3 zrzuty z podpisami: derywacje openssl pkeyutl -derive dla obu krzywych oraz KDF do klucza AES.
  3. Opisano w 2–3 zdaniach wybór narzędzi i dlaczego surowy sekret musi iść przez KDF (dydaktycznie SHA-256, produkcyjnie HKDF z solą/info RFC 5869).
  4. Zapisano wnioski (3–5 zdań): przemienność mnożenia skalarnego, przewaga rozmiaru/wydajności nad DH, KDF jako most do szyfru.

Wariant offline (fallback): Brak sieci/JSLinux: lokalny OpenSSL (Git-Bash/WSL) na plikach ze startera; CyberChef/kalkulatory zastąp opisem z cache i logiem openssl (rsa/ec/pkeyutl/derive/verify); dołącz pliki .pem/.der i zrzuty.

Sugerowane wnioski i podsumowanie - co student ma osiągnąć

Sprawozdanie z realizacji zadania musi zawierać następujące kluczowe wnioski i osiągnięcia:

  • Zrozumienie zasady działania protokołu ECDH opartego na przemienności mnożenia skalarnego punktów.
  • Praktyczna umiejętność derywacji wspólnego sekretu z kluczy X25519 oraz NIST P-256 w OpenSSL.
  • Zrozumienie konieczności przepuszczenia surowego sekretu przez funkcję KDF (dydaktycznie SHA-256; produkcyjnie HKDF z solą i info wg RFC 5869, por. 5.0/zad. 6).
  • Wykazanie ogromnej przewagi wydajnościowej i komunikacyjnej ECDH nad klasycznym protokołem DH.
Zadanie 6 - ilustracja
07/10
Zadanie 7. Tworzenie i weryfikacja podpisów cyfrowych RSA w formatach PKCS#1 v1.5 oraz RSA-PSS
🖥️ Wymagane środowisko:
System: Windows (bez praw administratora) + JSLinux Alpine w przeglądarce
Oprogramowanie: przeglądarka + CyberChef + OpenSSL
Podstawa wykładowa: Część 4 - slajdy 21, 22, 23, 27: koncepcja podpisu cyfrowego Hash-then-Sign, niezaprzeczalność i integralność, schemat deterministyczny PKCS#1 v1.5, probabilistyczny schemat RSA-PSS.

Cel

Celem zadania jest praktyczne opanowanie procedury generowania oraz weryfikacji podpisów cyfrowych RSA zgodnie ze schematem Hash-then-Sign. Student bada różnice pomiędzy deterministycznym standardem dopełnienia PKCS#1 v1.5 a probabilistycznym schematem RSA-PSS przy użyciu poleceń narzędzia OpenSSL w emulatorze JSLinux oraz serwisu CyberChef.

Scenariusz – opis

Podpis cyfrowy jest kryptograficznym odpowiednikiem podpisu odręcznego, zapewniającym autentyczność, integralność oraz niezaprzeczalność. Ze względów bezpieczeństwa i wydajności nie podpisuje się bezpośrednio całego dokumentu, lecz stosuje paradygmat Hash-then-Sign. Dokument jest najpierw redukowany do stałego skrótu kryptograficznego (np. SHA-256), a następnie skrót ten jest przetwarzany kluczem prywatnym nadawcy. Odbiorca weryfikuje podpis za pomocą klucza publicznego nadawcy, sprawdzając czy odtworzony skrót zgadza się ze skrótem otrzymanego pliku. W klasycznym standardzie PKCS#1 v1.5 podpis jest w pełni deterministyczny: ten sam dokument podpisany tym samym kluczem daje identyczny podpis. Nowoczesny standard RSA-PSS (Probabilistic Signature Scheme) wprowadza losową sól (salt) i funkcję maskującą MGF1, zapewniając dowodliwe bezpieczeństwo.

Co ma wykonać student / grupa

W konsoli JSLinux Alpine przygotowujesz klucz prywatny RSA-2048 oraz klucz publiczny wygenerowany w poprzednich zadaniach. Tworzysz dokument tekstowy umowa_lab4.txt zawierający oficjalną treść deklaracji laboratoryjnej. Podpisujesz dokument za pomocą klucza prywatnego poleceniem openssl dgst z flagą -sha256 i parametrem -sign do pliku podpis_pkcs1.bin. Weryfikujesz podpis za pomocą klucza publicznego poleceniem openssl dgst -sha256 -verify i rejestrujesz komunikat Verified OK.

Modyfikujesz dokładnie jeden znak w treści dokumentu umowa_lab4.txt i ponawiasz próbę weryfikacji podpisu. Rejestrujesz błąd Verification Failure, dowodząc pełnej ochrony integralności dokumentu przez podpis cyfrowy. Podpisujesz oryginalny dokument po raz drugi do pliku podpis_pkcs1_v2.bin i potwierdzasz ich binarną identyczność poleceniem cmp.

Następnie generujesz podpis w nowoczesnym standardzie RSA-PSS za pomocą flagi -sigopt rsa_padding_mode:pss z jawnymi -sigopt rsa_pss_saltlen:32 i -sigopt rsa_mgf1_md:sha256 do pliku podpis_pss1.bin. Podpisujesz ten sam dokument w trybie PSS po raz drugi do pliku podpis_pss2.bin i porównujesz oba pliki poleceniem cmp. Zauważasz, że podpisy PSS różnią się całkowicie pomimo identycznej treści dokumentu i klucza, co wynika z losowej soli. Weryfikujesz poprawność obu podpisów PSS poleceniem openssl dgst z flagami -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:32 -sigopt rsa_mgf1_md:sha256 i potwierdzasz ich ważność.

W serwisie CyberChef odtwarzasz procedurę weryfikacji podpisu za pomocą operacji Verify RSA Signature. Badany rozmiar podpisu RSA-2048 wynosi dokładnie 256 bajtów niezależnie od wybranego trybu paddingu.

Sporządzasz tabelę porównawczą właściwości PKCS#1 v1.5 oraz RSA-PSS pod kątem determinizmu, obecności soli i podatności. Zbierasz zrzuty ekranu komunikatów weryfikacji i kompletujesz sprawozdanie.

Przykładowe kroki do wykonania jako sugestia

  1. Uruchom maszynę JSLinux Alpine i upewnij się, że posiadasz rsa_priv_2048.pem oraz rsa_pub_2048.pem.
  2. Utwórz plik z umową: echo 'Oficjalna tresc deklaracji laboratoryjnej studenta' > umowa.txt.
  3. Wygeneruj podpis PKCS#1 v1.5 ze skrótem SHA-256: openssl dgst -sha256 -sign rsa_priv_2048.pem -out sig_pkcs1.bin umowa.txt.
  4. Zweryfikuj podpis kluczem publicznym: openssl dgst -sha256 -verify rsa_pub_2048.pem -signature sig_pkcs1.bin umowa.txt.
  5. Potwierdź obecność komunikatu 'Verified OK'.
  6. Zmodyfikuj treść umowy: echo 'Sfałszowana tresc deklaracji' > umowa_mod.txt.
  7. Spróbuj zweryfikować stary podpis dla zmodyfikowanego pliku: openssl dgst -sha256 -verify rsa_pub_2048.pem -signature sig_pkcs1.bin umowa_mod.txt.
  8. Zarejestruj komunikat błędu 'Verification Failure'.
  9. Wygeneruj drugi podpis PKCS#1 v1.5: openssl dgst -sha256 -sign rsa_priv_2048.pem -out sig_pkcs1_b.bin umowa.txt.
  10. Porównaj oba podpisy: cmp sig_pkcs1.bin sig_pkcs1_b.bin (pliki są identyczne).
  11. Wygeneruj podpis RSA-PSS: openssl dgst -sha256 -sign rsa_priv_2048.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:32 -sigopt rsa_mgf1_md:sha256 -out sig_pss1.bin umowa.txt.
  12. Wygeneruj drugi podpis RSA-PSS dla tego samego pliku: openssl dgst -sha256 -sign rsa_priv_2048.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:32 -sigopt rsa_mgf1_md:sha256 -out sig_pss2.bin umowa.txt.
  13. Porównaj oba podpisy PSS: cmp sig_pss1.bin sig_pss2.bin (pliki różnią się).
  14. Zweryfikuj oba podpisy PSS: openssl dgst -sha256 -verify rsa_pub_2048.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:32 -sigopt rsa_mgf1_md:sha256 -signature sig_pss1.bin umowa.txt (jawny saltlen 32 i mgf1 SHA-256 zapobiegają rozjazdom między wersjami OpenSSL).
  15. W CyberChef załaduj klucz publiczny i sprawdź weryfikację podpisu z operacją Verify RSA Signature.
  16. Wykonaj zrzuty ekranu i opracuj zestawienie wniosków w sprawozdaniu.

Kontrola zaliczenia (checklist):

  1. Zachowano artefakt: podpisany plik w obu schematach (PKCS#1 v1.5 i RSA-PSS) + logi weryfikacji OK oraz log odrzucenia po zmianie 1 bitu pliku.
  2. Dołączono 2–3 zrzuty z podpisami: komendy openssl dgst -sign/-verify dla obu paddingów oraz test integralności.
  3. Opisano w 2–3 zdaniach wybór narzędzi (OpenSSL do podpisu, CyberChef do podglądu DigestInfo/soli) i paradygmat Hash-then-Sign.
  4. Zapisano wnioski (3–5 zdań): skrót jako efektywność+bezpieczeństwo, determinizm v1.5 vs losowość PSS (sól/MGF1/0xBC).

Wariant offline (fallback): Brak sieci/JSLinux: lokalny OpenSSL (Git-Bash/WSL) na plikach ze startera; CyberChef/kalkulatory zastąp opisem z cache i logiem openssl (rsa/ec/pkeyutl/derive/verify); dołącz pliki .pem/.der i zrzuty.

Sugerowane wnioski i podsumowanie - co student ma osiągnąć

Sprawozdanie z realizacji zadania musi zawierać następujące kluczowe wnioski i osiągnięcia:

  • Zrozumienie paradygmatu Hash-then-Sign i roli funkcji skrótu w zapewnieniu efektywności i bezpieczeństwa podpisów.
  • Wykazanie natychmiastowego wykrywania jakiejkolwiek modyfikacji treści podpisanego dokumentu.
  • Rozróżnienie właściwości deterministycznego paddingu PKCS#1 v1.5 oraz probabilistycznego RSA-PSS.
  • Praktyczna umiejętność podpisywania plików i weryfikacji podpisów narzędziami OpenSSL i CyberChef.
Zadanie 7 - ilustracja
08/10
Zadanie 8. Podpisy cyfrowe oparte na krzywych eliptycznych ECDSA i Ed25519 w OpenSSL
🖥️ Wymagane środowisko:
System: Windows (bez praw administratora) + JSLinux Alpine w przeglądarce
Oprogramowanie: przeglądarka + OpenSSL
Podstawa wykładowa: Część 4 - slajdy 24, 25, 26, 37: algorytmy ECDSA (ANSI X9.62) i EdDSA (Ed25519, RFC 8032), skręcone krzywe Edwardsa, struktura podpisu r i s, szybkość i determinizm.

Cel

Celem zadania jest praktyczne zbadanie podpisów cyfrowych na krzywych eliptycznych przy użyciu algorytmów ECDSA (krzywa NIST P-256) oraz Ed25519 (EdDSA). Student analizuje strukturę formatu ASN.1 DER sygnatury ECDSA (para liczb r i s), porównuje ją ze stałą sygnaturą 64-bajtową w Ed25519 oraz bada szybkość i niezawodność obu rozwiązań w OpenSSL.

Scenariusz – opis

Podpisy oparte na krzywych eliptycznych stanowią współczesny standard zabezpieczeń w systemach operacyjnych, kryptowalutach i protokole SSH. Algorytm ECDSA stanowi adaptację klasycznego schematu DSA do grup punktów na krzywych eliptycznych Weierstrassa. Sygnatura ECDSA składa się z pary liczb całkowitych (r, s), które w formatach standardowych są serializowane w strukturze ASN.1 Sequence. Z powodu zmiennej długości liczb r i s oraz narzutu ASN.1 rozmiar wynikowego podpisu ECDSA P-256 waha się zazwyczaj w granicach 70-72 bajtów. Algorytm Ed25519 oparty na skręconej krzywej Edwardsa eliminuje wady ECDSA, oferując całkowicie deterministyczny podpis o stałej długości 64 bajtów. W Ed25519 podpis nie wymaga zewnętrznego generatora liczb losowych podczas podpisywania, co eliminuje katastrofalne błędy wycieku klucza.

Co ma wykonać student / grupa

W emulatorze JSLinux przygotowujesz klucz prywatny NIST P-256 ec_p256_priv.pem oraz wyodrębniasz klucz publiczny ec_p256_pub.pem. Generujesz również parę kluczy Ed25519 za pomocą polecenia openssl genpkey -algorithm ED25519 i zapisujesz do ed25519_priv.pem oraz ed25519_pub.pem. Tworzysz plik z danymi testowymi dokument_lab4.dat o rozmiarze kilkunastu kilobajtów. Podpisujesz plik algorytmem ECDSA z użyciem skrótu SHA-256: openssl dgst -sha256 -sign ec_p256_priv.pem -out ecdsa_sig.der dokument_lab4.dat.

Weryfikujesz podpis poleceniem openssl dgst -sha256 -verify ec_p256_pub.pem -signature ecdsa_sig.der dokument_lab4.dat. Badany plik podpisu ecdsa_sig.der poddajesz inspekcji poleceniem openssl asn1parse -inform DER -in ecdsa_sig.der. Identyfikujesz w drzewie ASN.1 dwa pola typu INTEGER reprezentujące składowe r oraz s podpisu ECDSA.

Następnie podpisujesz ten sam dokument za pomocą algorytmu Ed25519 poleceniem openssl pkeyutl -sign -inkey ed25519_priv.pem -outed25519_sig.bin. Weryfikujesz podpis Ed25519 poleceniem openssl pkeyutl -verify -pubin -inkey ed25519_pub.pem -sigfile ed25519_sig.bin. Sprawdzasz dokładny rozmiar pliku ed25519_sig.bin poleceniem ls-l i stwierdzasz, że wynosi on dokładnie 64 bajty (512 bitów). Generujesz podpis Ed25519 po raz drugi dla tego samego dokumentu i porównujesz poleceniem cmp, potwierdzając jego determinizm.

Mierzysz czasy podpisywania obu algorytmów za pomocą wbudowanego benchmarku openssl speed ecdsap256 oraz openssl speed ed25519. Zauważasz zdecydowaną przewagę wydajnościową algorytmu Ed25519 nad ECDSA i RSA.

Sporządzasz tabelę zestawiającą rozmiar kluczy, rozmiar podpisu, determinizm oraz szybkość dla RSA-2048, ECDSA P-256 i Ed25519. Kompletujesz materiały dowodowe i przygotowujesz sprawozdanie. Stosujesz ramkę narzędziową: dgst (hash+sign w jednym, tu dla ECDSA) vs pkeyutl (surowy sign/verify, wymagany dla Ed25519) oraz wykonujesz test negatywny - podmiana 1 B podpisu musi dać Verification Failure.

Przykładowe kroki do wykonania jako sugestia

  1. W konsoli JSLinux wygeneruj klucz P-256: openssl ecparam -name prime256v1 -genkey -noout -out p256_key.pem && openssl ec -in p256_key.pem -pubout -out p256_pub.pem.
  2. Wygeneruj klucz Ed25519: openssl genpkey -algorithm ED25519 -out ed_key.pem && openssl pkey -in ed_key.pem -pubout -out ed_pub.pem.
  3. Utwórz plik testowy: echo 'Dane autoryzacyjne transakcji elektronicznej' > doc.txt.
  4. Podpisz plik za pomocą ECDSA: openssl dgst -sha256 -sign p256_key.pem -out sig_ecdsa.der doc.txt.
  5. Zweryfikuj podpis ECDSA: openssl dgst -sha256 -verify p256_pub.pem -signature sig_ecdsa.der doc.txt.
  6. Potwierdź komunikat 'Verified OK'.
  7. Zbadaj strukturę ASN.1 podpisu ECDSA: openssl asn1parse -inform DER -in sig_ecdsa.der.
  8. Odczytaj długości całkowite liczb r i s w wyjściu asn1parse.
  9. Podpisz plik za pomocą Ed25519: openssl pkeyutl -sign -inkey ed_key.pem -in doc.txt -out sig_ed.raw.
  10. Zweryfikuj podpis Ed25519: openssl pkeyutl -verify -pubin -inkey ed_pub.pem -sigfile sig_ed.raw -in doc.txt.
  11. Sprawdź dokładny rozmiar pliku podpisu Ed25519: ls -l sig_ed.raw (dokładnie 64 bajty).
  12. Podpisz ten sam plik ponownie: openssl pkeyutl -sign -inkey ed_key.pem -in doc.txt -out sig_ed_k2.raw.
  13. Porównaj oba podpisy Ed25519: cmp sig_ed.raw sig_ed_k2.raw (pliki są identyczne).
  14. Wykonaj test negatywny: podmień 1 B w sig_ed.raw (dd) i potwierdź odrzucenie weryfikacji pkeyutl -verify (Failure) - ramka: dgst robi hash+sign w jednym (ECDSA), pkeyutl robi surowy sign/verify (wymagany dla Ed25519).
  15. Uruchom benchmark prędkości w OpenSSL: openssl speed ecdsap256.
  16. Wykonaj zrzuty ekranu drzewa ASN.1 oraz wyników weryfikacji obu podpisów.
  17. Opracuj podsumowanie porównujące bezpieczeństwo deterministycznego Ed25519 z losowym ECDSA.

Kontrola zaliczenia (checklist):

  1. Zachowano artefakt: podpisy ECDSA P-256 (DER z r,s) i Ed25519 (64 B) dla tego samego pliku + logi weryfikacji OK i odrzucenia po modyfikacji.
  2. Dołączono 2–3 zrzuty z podpisami: generowanie/weryfikacja openssl dla obu algorytmów oraz porównanie rozmiarów podpisów.
  3. Opisano w 2–3 zdaniach wybór narzędzi i sposób odczytu r,s z DER (asn1parse).
  4. Zapisano wnioski (3–5 zdań): DER (r,s) vs stałe 64 B, determinizm i odporność czasowa Ed25519, przewaga Edwardsa nad RSA/ECDSA.

Wariant offline (fallback): Brak sieci/JSLinux: lokalny OpenSSL (Git-Bash/WSL) na plikach ze startera; CyberChef/kalkulatory zastąp opisem z cache i logiem openssl (rsa/ec/pkeyutl/derive/verify); dołącz pliki .pem/.der i zrzuty.

Sugerowane wnioski i podsumowanie - co student ma osiągnąć

Sprawozdanie z realizacji zadania musi zawierać następujące kluczowe wnioski i osiągnięcia:

  • Zrozumienie struktury podpisów ECDSA jako pary (r, s) kodowanej w sekwencji ASN.1 DER.
  • Zrozumienie zalet architektury Ed25519: stały 64-bajtowy rozmiar podpisu, wysoka odporność na ataki czasowe i wbudowany determinizm.
  • Praktyczna umiejętność podpisywania danych i weryfikacji podpisów ECDSA i EdDSA narzędziami OpenSSL.
  • Świadomość przewagi wydajnościowej nowoczesnych krzywych Edwardsa nad tradycyjnymi podpisami RSA i ECDSA.
Zadanie 8 - ilustracja
09/10
Zadanie 9. Praktyczne badanie kolizji skrótów SHA-1 w podpisach cyfrowych na przykładzie pary SHAttered
🖥️ Wymagane środowisko:
System: Windows (bez praw administratora) + JSLinux Alpine w przeglądarce
Oprogramowanie: przeglądarka + CyberChef + OpenSSL
Podstawa wykładowa: Część 4 - slajdy 28, 29, 31: odporność na kolizje funkcji skrótu, atak SHAttered na SHA-1 (2017), dwa różne pliki o identycznym skrócie SHA-1, kompromitacja podpisów cyfrowych.

Cel

Celem zadania jest praktyczne zbadanie skutków złamania odporności na kolizje funkcji skrótu SHA-1 dla ważności podpisów cyfrowych. Student analizuje parę plików kolizyjnych SHAttered, weryfikuje ich sumy kontrolne SHA-1 oraz SHA-256, a następnie dowodzi, że podpis cyfrowy oparty na SHA-1 jest formalnie poprawny dla dwóch zupełnie różnych dokumentów.

Scenariusz – opis

Bezpieczeństwo schematu podpisu Hash-then-Sign opiera się bezpośrednio na odporności funkcji skrótu na kolizje. Odporność na kolizje oznacza, że znalezienie dwóch dowolnych różnych wiadomości m1 != m2 takich, że H(m1) = H(m2), musi być obliczeniowo niewykonalne. W lutym 2017 roku zespół badaczy z CWI Amsterdam i Google ogłosił atak SHAttered, generując pierwszą praktyczną kolizję SHA-1 dla dwóch plików PDF. Oba pliki PDF mają całkowicie różną zawartość wizualną (jeden ma niebieskie tło, a drugi czerwone), lecz posiadają dokładnie ten sam 160-bitowy skrót SHA-1. Jeśli użytkownik podpisze cyfrowo dokument m1 za pomocą algorytmu opartego na SHA-1, ten sam podpis będzie matematycznie poprawny dla dokumentu m2. Oznacza to całkowitą utratę niezaprzeczalności i możliwość bezkarnego podmienienia podpisanej umowy na fałszywy dokument.

Co ma wykonać student / grupa

W terminalu JSLinux lub w przeglądarce przygotowujesz dwa pliki demonstracyjne kolizji SHAttered (pracujesz na samych blokach kolizyjnych, kilka kB, z sumami do weryfikacji - nie na pełnych 422 kB PDF-ach). Weryfikujesz bloki linkiem do oficjalnego repo SHAttered z hashami SHA-256 próbek (sha1sum musi być równe, sha256sum różne). Weryfikujesz rozmiary obu plików poleceniem ls-l i sprawdzasz, czy są równe co do bajta. Obliczasz skróty SHA-1 obu plików za pomocą polecenia sha1sum w konsoli JSLinux. Rejestrujesz fakt, że sumy kontrolne SHA-1 obu różnych plików są absolutnie identyczne.

Następnie obliczasz skróty SHA-256 obu plików za pomocą polecenia sha256sum. Przekonujesz się, że sumy SHA-256 różnią się diametralnie, co dowodzi, że kolizja dotyczy wyłącznie wadliwego algorytmu SHA-1. Generujesz parę kluczy RSA-2048 do celów podpisania dokumentu za pomocą openssl genpkey. Podpisujesz pierwszy plik za pomocą wadliwego schematu opartego o SHA-1: openssl dgst -sha1 -sign klucz_priv.pem -outpodpis_shattered.binplik_a.pdf. Weryfikujesz podpis względem pierwszego pliku: openssl dgst -sha1 -verify klucz_pub.pem -signature podpis_shattered.binplik_a.pdf (Verified OK).

Teraz przeprowadzasz kluczowy test: weryfikujesz ten sam podpis względem drugiego, zupełnie innego pliku plik_b.pdf. Zauważasz zjawisko kryptoanalityczne: system zwraca komunikat Verified OK, uznając fałszywy dokument za autentycznie podpisany. Powtarzasz procedurę z użyciem bezpiecznej funkcji skrótu SHA-256 i odnotowujesz natychmiastowe odrzucenie fałszerstwa (Verification Failure). W serwisie CyberChef wgrywasz oba pliki i generujesz ich sumy kontrolne MD5, SHA-1 oraz SHA-256. Dokumentujesz zrzutami ekranu przebieg fałszowania podpisu oraz wyliczone sumy kontrolne. Formułujesz wyczerpujące podsumowanie wyjaśniające, dlaczego wszystkie standardy branżowe całkowicie zakazują używania SHA-1 w infrastrukturze PKI.

Przykładowe kroki do wykonania jako sugestia

  1. Uruchom konsolę JSLinux Alpine.
  2. Pobierz lub wygeneruj parę bloków kolizyjnych SHA-1 (samo jądro kolizji, kilka kB z oficjalnego repo SHAttered wraz z hashami SHA-256 do weryfikacji - nie pełne 422 kB PDF-y).
  3. Sprawdź sumy SHA-1 obu plików: sha1sum shattered-1.pdf shattered-2.pdf.
  4. Potwierdź, że oba hashe SHA-1 są całkowicie identyczne (38762cf7f55934b34d179ae6a4c80cadccbb7f0a).
  5. Sprawdź sumy SHA-256 obu plików: sha256sum shattered-1.pdf shattered-2.pdf.
  6. Potwierdź, że hashe SHA-256 są zupełnie różne.
  7. Sprawdź różnice binarne w plikach poleceniem: cmp -l shattered-1.pdf shattered-2.pdf | wc -l.
  8. Wygeneruj klucz testowy RSA: openssl genpkey -algorithm RSA -out rsa_shattered.pem && openssl pkey -in rsa_shattered.pem -pubout -out rsa_shat_pub.pem.
  9. Podpisz plik shattered-1.pdf przy użyciu SHA-1: openssl dgst -sha1 -sign rsa_shattered.pem -out sig_shat.bin shattered-1.pdf.
  10. Zweryfikuj podpis pod shattered-1.pdf: openssl dgst -sha1 -verify rsa_shat_pub.pem -signature sig_shat.bin shattered-1.pdf.
  11. Zweryfikuj TEN SAM podpis pod shattered-2.pdf: openssl dgst -sha1 -verify rsa_shat_pub.pem -signature sig_shat.bin shattered-2.pdf.
  12. Zarejestruj sukces weryfikacji 'Verified OK' dla drugiego, niepodpisanego dokumentu.
  13. Podpisz plik shattered-1.pdf przy użyciu SHA-256: openssl dgst -sha256 -sign rsa_shattered.pem -out sig_sha256.bin shattered-1.pdf.
  14. Spróbuj zweryfikować podpis SHA-256 pod shattered-2.pdf i zarejestruj błąd 'Verification Failure'.
  15. W CyberChef porównaj działanie SHA-1 i SHA-256 na obu wektorach testowych.
  16. Wykonaj zrzuty ekranu i opracuj analizę wpływu kolizji na certyfikaty X.509.

Kontrola zaliczenia (checklist):

  1. Zachowano artefakt: para SHAttered (dwa różne PDF, identyczny SHA-1, różne SHA-256) z logiem sha1sum/sha256sum oraz log weryfikacji podpisu (fałszywy przechodzi na SHA-1, odpada na SHA-256).
  2. Dołączono 2–3 zrzuty z podpisami: sumy obu plików obok siebie oraz test podpisu/weryfikacji.
  3. Opisano w 2–3 zdaniach wybór narzędzi i pochodzenie pary kolizyjnej (wektory SHAttered ze startera).
  4. Zapisano wnioski (3–5 zdań): kolizja = fałszerstwo podpisu pod inny dokument, collision resistance jako warunek niezaprzeczalności, wycofanie SHA-1.

Wariant offline (fallback): Brak sieci/JSLinux: lokalny OpenSSL (Git-Bash/WSL) na plikach ze startera; CyberChef/kalkulatory zastąp opisem z cache i logiem openssl (rsa/ec/pkeyutl/derive/verify); dołącz pliki .pem/.der i zrzuty.

Sugerowane wnioski i podsumowanie - co student ma osiągnąć

Sprawozdanie z realizacji zadania musi zawierać następujące kluczowe wnioski i osiągnięcia:

  • Praktyczny dowód na to, że kolizja funkcji skrótu pozwala na sfałszowanie podpisu cyfrowego pod zupełnie innym dokumentem.
  • Zrozumienie fundamentalnego znaczenia odporności na kolizje (Collision Resistance) dla niezaprzeczalności podpisów.
  • Wykazanie, że funkcja SHA-256 skutecznie chroni przed atakiem, generując całkowicie odmienne skróty dla pary SHAttered.
  • Świadomość historycznych konsekwencji ataku SHAttered dla wycofania SHA-1 ze wszystkich gałęzi bezpieczeństwa IT.
Zadanie 9 - ilustracja
10/10
Zadanie 10. Prosty model szyfrowania hybrydowego: kapsułkowanie klucza AES-GCM kluczem publicznym RSA
🖥️ Wymagane środowisko:
System: Windows (bez praw administratora) + JSLinux Alpine w przeglądarce
Oprogramowanie: przeglądarka + CyberChef + OpenSSL
Podstawa wykładowa: Część 4 - slajdy 32, 33: szyfrowanie hybrydowe, podział na mechanizm KEM (Key Encapsulation Mechanism) oraz DEM (Data Encapsulation Mechanism), wydajność szyfrowania masowego.

Cel

Celem zadania jest praktyczna implementacja i analiza klasycznego modelu szyfrowania hybrydowego (KEM + DEM). Student łączy zalety szyfrowania asymetrycznego RSA (bezpieczna dystrybucja klucza bez wcześniejszego sekretu) z wydajnością i integralnością szyfrowania symetrycznego AES-256-GCM przy użyciu narzędzi konsolowych OpenSSL oraz serwisu CyberChef.

Scenariusz – opis

W praktyce kryptograficznej algorytmy asymetryczne (jak RSA) są zbyt wolne do bezpośredniego szyfrowania dużych plików i strumieni danych. Ponadto algorytmy asymetryczne posiadają sztywne limity rozmiaru danych wejściowych, ograniczone wielkością klucza. Z tego względu we współczesnych protokołach stosuje się model szyfrowania hybrydowego (ang. Hybrid Encryption). Model ten dzieli się na dwa komponenty: mechanizm kapsułkowania klucza KEM oraz mechanizm kapsułkowania danych DEM. W fazie KEM nadawca generuje losowy, jednorazowy klucz symetryczny i szyfruje go kluczem publicznym odbiorcy. W fazie DEM właściwe dane o dowolnym rozmiarze są szyfrowane wygenerowanym kluczem symetrycznym przy użyciu wydajnego algorytmu AEAD (np. AES-GCM).

Co ma wykonać student / grupa

W emulatorze JSLinux przygotowujesz klucz prywatny oraz publiczny RSA-2048 odbiorcy (Bob). Tworzysz duży plik danych testowych dane_duze.bin o rozmiarze 10 MB za pomocą polecenia dd z generatora pseudolosowego /dev/urandom. Sprawdzasz, że bezpośrednia próba zaszyfrowania tego pliku kluczem RSA kończy się błędem ze względu na limit 190 bajtów. Przystępujesz do realizacji schematu hybrydowego: generujesz losowy 256-bitowy klucz symetryczny poleceniem openssl rand 32 i zapisujesz do sesja.key.

Generujesz również losowy 12-bajtowy wektor IV dla trybu GCM poleceniem openssl rand 12 i zapisujesz do sesja.iv. Szyfrujesz plik danych testowych za pomocą symetrycznego szyfru AES-256-GCM poleceniem opensslenc -aes-256-gcm z kluczem sesja.key i zapisujesz do szyfrogram_dane.enc (tryb AEAD z tagiem; wariant CBC dopuszczalny tylko po przemianowaniu zadania na CBC). W teście integralności podmieniasz 1 B szyfrogramu i potwierdzasz błąd InvalidTag (dla GCM) - produkcyjnie wymagany jest GCM/AEAD, nie samo CBC. Kapsułkujesz jednorazowy klucz symetryczny: szyfrujesz plik sesja.key kluczem publicznym Boba za pomocą openssl pkeyutl -encrypt z paddingiem OAEP.

Zapisujesz zaszyfrowany klucz do pliku klucz_kapsula.enc o rozmiarze dokładnie 256 bajtów. Pakietem przesyłanym do odbiorcy jest zestaw: klucz_kapsula.enc, sesja.iv oraz szyfrogram_dane.enc.

Przechodzisz do roli Boba i realizujesz proces deszyfrowania hybrydowego. Odszyfrowujesz kapsułę klucza kluczem prywatnym Boba za pomocą openssl pkeyutl -decrypt do pliku odzyskany_klucz.key. Odszyfrowujesz właściwe dane szyfrem AES-256-GCM za pomocą odzyskanego klucza do pliku dane_odzyskane.bin. Weryfikujesz integralność danych za pomocą polecenia cmp oraz porównując sumy kontrolne sha256sum pliku źródłowego i odzyskanego. W serwisie CyberChef weryfikujesz analogiczny proces dekapsułkowania klucza i deszyfrowania danych.

Sporządzasz wykres lub tabelę porównującą czas i narzuty szyfrowania hybrydowego w stosunku do czystego szyfrowania asymetrycznego. Kompletujesz pełne sprawozdanie laboratoryjne z realizacji zadania.

Przykładowe kroki do wykonania jako sugestia

  1. W konsoli JSLinux upewnij się, że posiadasz parę kluczy rsa_pub_2048.pem oraz rsa_priv_2048.pem.
  2. Wygeneruj duży plik testowy o rozmiarze 5 MB: dd if=/dev/urandom of=plik_duzy.bin bs=1M count=5.
  3. Sprawdź rozmiar pliku poleceniem ls -lh plik_duzy.bin.
  4. Wygeneruj losowy 256-bitowy klucz sesyjny AES: openssl rand -out sesja.key 32.
  5. Wygeneruj losowy 12-bajtowy wektor IV: openssl rand -out sesja.iv 12.
  6. Przekonwertuj klucz i IV do formatu hex: xxd -p sesja.key | tr -d '\n' > k.hex && xxd -p sesja.iv | tr -d '\n' > iv.hex.
  7. Zaszyfruj plik symetrycznie za pomocą AES-256-GCM: openssl enc -aes-256-gcm -in plik_duzy.bin -out plik_c.bin -K $(cat k.hex) -iv $(cat iv.hex) (AEAD z tagiem; nie CBC bez tagu).
  8. Zakapsułkuj klucz sesyjny kluczem publicznym RSA w trybie OAEP: openssl pkeyutl -encrypt -pubin -inkey rsa_pub_2048.pem -in sesja.key -out kapsula.enc -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256.
  9. Sprawdź rozmiary plików: ls -lh plik_c.bin kapsula.enc.
  10. Odkapsułkuj klucz sesyjny kluczem prywatnym RSA: openssl pkeyutl -decrypt -inkey rsa_priv_2048.pem -in kapsula.enc -out klucz_odyskany.key -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256.
  11. Zweryfikuj tożsamość klucza sesyjnego: cmp sesja.key klucz_odyskany.key.
  12. Przygotuj hex odzyskanego klucza: xxd -p klucz_odyskany.key | tr -d '\n' > k_rec.hex.
  13. Odszyfruj plik symetryczny: openssl enc -d -aes-256-gcm -in plik_c.bin -out plik_odyskany.bin -K $(cat k_rec.hex) -iv $(cat iv.hex).
  14. Sprawdź integralność danych wyjściowych: cmp plik_duzy.bin plik_odyskany.bin.
  15. Wykonaj test AEAD: podmień 1 B w plik_c.bin i potwierdź odrzucenie deszyfrowania (InvalidTag).
  16. W CyberChef przetestuj procedurę odszyfrowania kapsuły klucza oraz właściwego szyfrogramu.
  17. Wykonaj zrzuty ekranu poleceń i opracuj schemat przepływu danych KEM/DEM w sprawozdaniu.

Kontrola zaliczenia (checklist):

  1. Zachowano artefakt: paczka hybrydowa (klucz AES owinięty RSA-OAEP + dane w AES-GCM z tagiem) + log poprawnego odpakowania i odszyfrowania oraz rozmiar danych >> moduł RSA.
  2. Dołączono 2–3 zrzuty z podpisami: kapsułkowanie (pkeyutl), szyfrowanie DEM (enc -aes-256-gcm) oraz dekapsułowanie zwrotne.
  3. Opisano w 2–3 zdaniach wybór narzędzi i podział ról KEM (RSA) + DEM (AES-GCM).
  4. Zapisano wnioski (3–5 zdań): RSA tylko do klucza, symetryk do danych bez limitu, model PGP/SMIME/TLS i baza pod PQC.

Wariant offline (fallback): Brak sieci/JSLinux: lokalny OpenSSL (Git-Bash/WSL) na plikach ze startera; CyberChef/kalkulatory zastąp opisem z cache i logiem openssl (rsa/ec/pkeyutl/derive/verify); dołącz pliki .pem/.der i zrzuty.

Sugerowane wnioski i podsumowanie - co student ma osiągnąć

Sprawozdanie z realizacji zadania musi zawierać następujące kluczowe wnioski i osiągnięcia:

  • Zrozumienie fundamentalnej architektury szyfrowania hybrydowego łączącej mechanizmy KEM i DEM.
  • Praktyczna umiejętność bezpiecznego kapsułkowania klucza symetrycznego za pomocą asymetrycznego algorytmu RSA-OAEP.
  • Wykazanie braku ograniczeń na rozmiar szyfrowanych danych dzięki wykorzystaniu szyfrów symetrycznych.
  • Zrozumienie, w jaki sposób model hybrydowy stanowi podstawę protokołów PGP, S/MIME, TLS oraz nowoczesnych standardów PQC.
Zadanie 10 - ilustracja
Podgląd