Seminarium rozwiązywania problemów programistycznych
Transkrypt
Seminarium rozwiązywania problemów programistycznych
Seminarium rozwiązywania problemów programistycznych Zadanie 2. Szyfr Vigenère’a 1 Wprowadzenie Szyfrowanie jest procesem mającym na celu takie zakodowanie informacji, aby była ona dostępna tylko dla tych osób, dla których jest przeznaczona. Istnieje wiele różnych algorytmów szyfrujących. Treścią tego zadania jest stworzenie programu łamiącego szyfr Vigenère’a. Zanim zapoznamy się z metodami szyfrowania konieczne będzie przedstawienie kilku podstawowych informacji. Przyjęło się w kryptografii, że pisząc o szyfrowaniu używa się małych liter dla oznaczenia tekstu jawnego, a wielkich dla tekstu zaszyfrowanego i będziemy tej konwencji przestrzegać w tym opisie. Tym niemniej będziemy zakładać, że prawdziwe teksty, które będziemy szyfrowali będą się składały wyłącznie z wielkich liter. Nie będziemy się tu zajmowali najnowocześniejszymi szyframi i w związku z tym będziemy modyfikowali tekst przed szyfrowaniem, tak jak to robili kryptografowie, kiedy jeszcze nie wykorzystywali do szyfrowania komputerów, Wspomniana modyfikacja polega na usunięciu z tekstu jawnego wszystkich znaków interpunkcyjnych, spacji, znaków nowego wiersza, itd. Będziemy więc zakładali, że szyfrowany tekst składa się wyłącznie z wielkich liter. Przyjmiemy również, że wszystkie teksty są zapisane w języku angielskim. 2 Szyfr Cezara Jednym z najprostszych szyfrów jest szyfr Cezara, który był już stosowany przez Juliusza Cezara. Zasada działania tego szyfru jest bardzo prosta. Każdej literze alfabetu jawnego przyporządkowana jest litera przesunięta w alfabecie o pewną liczbę pozycji. Przykład tablicy kodowej przedstawia rysunek 1, a na rysunku 2 pokazany jest proces szyfrowania. alfabet jawny alfabet szyfrowy a b c d e f g h i j k l m n o p q r s t u v w x y z D E F G H I J K L M N O P Q R S T U V W X Y Z A B C Rysunek 1: Przykładowa tablica kodowa dla szyfru Cezara z przesunięciem o 3 znaki. tekst jawny tekst zaszyfrowany i a m b o n d j a m e s b o n d L D P E R Q G M D P H V E R Q G Rysunek 2: Szyfrowania metodą Cezara. Jak widzimy różnych sposobów zaszyfrowania tekstu jawnego jest tylko 25, gdyż jedynie tyle mamy różnych możliwości przesunięcia alfabetu szyfrowego. Kluczem w tym szyfrze jest odległość o jaką są przesunięte litery alfabetu. Złamanie tego szyfru nie jest więc żadnym problemem. Wystarczy jedynie wypróbować wszystkie 25 możliwości i sprawdzić, dla której z nich otrzymamy tekst, który ma sens. 3 Szyfr podstawieniowy Bardziej skomplikowanym i też trudniejszym do złamania szyfrem jest szyfr podstawieniowy. Metoda ta opiera się również na tablicy kodowej, która jest jednak tworzona w inny sposób. Każdej literze przyporządkowywana jest litera, ale nie już nie w ten sposób, że wykonywane jest zwykłe przesunięcie alfabetu. Przykład tablicy kodowej został przedstawiony na rysunku 3. alfabet jawny alfabet szyfrowy a b c d e f g h i j k l m n o p q r s t u v w x y z K E Q N A J Z P W G B O I X W C Y D R S F L H U M T Rysunek 3: Przykładowa tablica kodowa dla szyfru podstawieniowego. 1 tekst jawny tekst zaszyfrowany i a m b o n d j a m e s b o n d W K I E W X N G B I A R E W X N Rysunek 4: Przykład działania szyfru podstawieniowego. Oczywiście aby szyfr był odwracalny musimy zapewnić, aby w alfabecie szyfrowym każda litera występowała dokładnie jeden raz. Kluczem w tej metodzie szyfrowania jest kolejność liter w alfabecie szyfrowym. Jak łatwo obliczyć, różnych możliwości wyboru klucza jest 26! = 403291461126605635584000000. Przykład szyfrowania tym algorytmem jest przedstawiony na rysunku 4. Proces deszyfracji jest oczywiście bardzo podobny. Wykorzystujemy tą samą tablicę kodową i dla każdej litery tekstu zaszyfrowanego wyszukujemy odpowiadającą jej literę w alfabecie jawnym. Ze względu dużą liczbę możliwych kluczy łamanie tego szyfru przez sprawdzenie wszystkich możliwości (atak brute force) nie jest dobrym pomysłem. O wiele lepszą metodą jest wykorzystanie tzw. tablicy częstości, która zawiera średnią częstość wystąpień liter w tekstach zapisanych w danym języku (w naszym wypadku w języku angielskim). Przykładową tabelę częstości pokazano na rysunku 5. litera a b c d e f g h i j k l m procent 8,2 1,5 2,8 4,3 12,7 2,2 2,0 6,1 7,0 0,2 0,8 4,0 2,4 litera n o p q r s t u v w x y z procent 6,7 7,5 1,9 0,1 6,0 6,3 9,1 2,8 1,0 2,4 0,2 2,0 0,1 Rysunek 5: Tabela częstości występowania liter w tekstach zapisanych w języku angielskim za [1]. Jak można łatwo zauważyć najczęściej występującą literą w języku angielskim jest e, a najrzadziej pojawiają się j, k, q, x, z. Można wykorzystać tą wiedzę i założyć, że litera w tekście zaszyfrowanym, która pojawia się najczęściej odpowiada właśnie literze e w tekście jawnym. Podobne założenie można uczynić dla innych liter posługując się tablicą częstości. Ze względu na fluktuacje częstości oczywiście nie zawsze uda się nam od razu poprawnie dopasować litery, ale liczba prób dramatycznie się zmniejsza. Można również wykorzystać fakt, że najczęściej pojawiającymi się parami liter w języku angielskim są ss, ee, tt, ll, mm, oo. Jeśli w tekście zaszyfrowanym występują powtarzające się pary liter to z dużym prawdopodobieństwem można założyć, że reprezentują one właśnie te litery. Bardzo często zdarza się, że po założeniu kilku liter udaje się odczytać fragment tekstu odgadując czasami brakujące litery w niektórych słowach. Dzięki temu uzyskujemy kolejne przyporządkowanie i systematycznie odbudowujemy całą tablicę kodową odgadując klucz i deszyfrując wiadomość. Podejście oparte na tablicy częstości można zastosować dlatego, że określonej literze w tekście jawnym zawsze odpowiada jedna i ta sama litera w tekście zaszyfrowanym. 4 Szyfr Vigenère’a Modyfikacją metody szyfrowania przez podstawienie, która usuwa wady szyfru podstawieniowego jest szyfr Vigenère’a, który został zaproponowany w XVI wieku przez Blaise’a de Vigenr̀e’a. Autor zaproponował żeby zamiast jednego alfabetu szyfrowego zastosować ich 26. W ten sposób zbudował tzw. tablicę Vigenère’a przedstawioną na rysunku 6. Kolejne litery tekstu jawnego są szyfrowane przez podstawienie według jednego z alfabetów szyfrowych. O tym, który alfabet zostanie wybrany do szyfrowania kolejnej litery decyduje klucz będący słowem (lub zbitką liku słów). Przeanalizujmy proces szyfrowania przedstawiony na rys 7. Nad tekstem jawnym wypisujemy słowo kluczowe powtarzając je tyle razy ile to potrzebne. Następnie przeprowadzamy szyfrowanie. Dla pierwszej litery, i, wybieramy alfabet szyfrowy oznaczony przez odpowiednią literę 2 alfabet 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 jawny A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a A B C D E F G H I J K L M N O P Q R S T U V W X Y Z b B C D E F G H I J K L M N O P Q R S T U V W X Y Z A c C D E F G H I J K L M N O P Q R S T U V W X Y Z A B d D E F G H I J K L M N O P Q R S T U V W X Y Z A B C e E F G H I J K L M N O P Q R S T U V W X Y Z A B C D f F G H I J K L M N O P Q R S T U V W X Y Z A B C D E g G H I J K L M N O P Q R S T U V W X Y Z A B C D E F h H I J K L M N O P Q R S T U V W X Y Z A B C D E F G i I J K L M N O P Q R S T U V W X Y Z A B C D E F G H j J K L M N O P Q R S T U V W X Y Z A B C D E F G H I k K L M N O P Q R S T U V W X Y Z A B C D E F G H I J l L M N O P Q R S T U V W X Y Z A B C D E F G H I J K m M N O P Q R S T U V W X Y Z A B C D E F G H I J K L n N O P Q R S T U V W X Y Z A B C D E F G H I J K L M o O P Q R S T U V W X Y Z A B C D E F G H I J K L M N p P Q R S T U V W X Y Z A B C D E F G H I J K L M N O q Q R S T U V W X Y Z A B C D E F G H I J K L M N O P r R S T U V W X Y Z A B C D E F G H I J K L M N O P Q s S T U V W X Y Z A B C D E F G H I J K L M N O P Q R t T U V W X Y Z A B C D E F G H I J K L M N O P Q R S u U V W X Y Z A B C D E F G H I J K L M N O P Q R S T v V W X Y Z A B C D E F G H I J K L M N O P Q R S T U w W X Y Z A B C D E F G H I J K L M N O P Q R S T U V x X Y Z A B C D E F G H I J K L M N O P Q R S T U V W y Y Z A B C D E F G H I J K L M N O P Q R S T U V W X z Z A B C D E F G H I J K L M N O P Q R S T U V W X Y Rysunek 6: Tablica Vigenère’a. klucza czyli A otrzymując zaszyfrowaną literę I. Dla drugiej litery tekstu jawnego, a, wybieramy alfabet szyfrowy opisany przez G otrzymując zakodowaną literę G. klucz tekst jawny tekst zaszyfrowany A G E N T A G E N T A G E N T A i a m b o n d j a m e s b o n d I G Q O H N J N N F E Y F B G D Rysunek 7: Szyfrowanie metodą Vigenère’a. Siła tego algorytmu polega na tym, że do kodowania kolejnych liter wybieramy różne alfabety szyfrowe dzięki czemu nawet jeśli jakaś litera występuje w tekście jawnym często, to jest ona kodowana na różne litery i nie możemy już zastosować klasycznego podejścia z użyciem tablicy częstości. Jeśli w tekście jawnym występują pary powtarzających się liter (takie jak ss, ee), to obydwie litery są kodowane na różne sposoby i też nie możemy tego wykorzystać. Trudno też zaatakować ten szyfr stosując sprawdzenie wszystkich możliwości, gdyż liczba możliwych kluczy wynosi 26k , gdzie k jest długością klucza użytego do szyfrowania. Szyfr ten uchodził przez prawie trzy stulecia za niemożliwy do złamania. Tym niemniej w XIX wieku Charles Babbage znalazł sposób jego łamania. Zastosowanie jego podejścia jest treścią naszego zadania. 5 Łamanie szyfru Vigenère’a Najważniejszą obserwacją Babbage’a było to, że jeśli jakieś słowo, np. the, występuje w tekście wiele razy to jest ono kodowane za pomocą różnych fragmentów klucza. W naszym przykładzie pierwsze wystąpienie słowa bond zostało zakodowane za pomocą fragmentu klucza NTAG, a drugie za pomocą ENTA. Tym niemniej, jeśli słowo występuje w tekście więcej razy to istnieje duża szansa, że zostanie ono zakodowane co najmniej kilka razy za pomocą tego samego fragmentu klucza, a więc dostaniemy powtarzające się fragmenty tekstu zaszyfrowanego, które mu odpowiadają. Regularności w tekście zaszyfrowanym są 3 właśnie tym czego szuka kryptoanalityk. Znajdując powtarzające się kilkuliterowe fragmenty w tekście zaszyfrowanym możemy obliczyć odległości między nimi. Jeśli powtórzenia nie były dziełem przypadku, to otrzymane odległości są wielokrotnościami długości klucza. Obliczając ich wspólne dzielniki możemy odgadnąć jaką długość ma klucz. Podejrzewając jaką długość ma klucz — oznaczmy ją przez k — możemy przystąpić do drugiej części kryptoanalizy. Budujemy teraz tablice częstości liter występujących w tekście zaszyfrowanym na tych samych pozycjach modulo k i porównujemy je ze znaną tabelą częstości wystąpień liter próbując odgadnąć, która tablica została wykorzystana do szyfrowania, a co za tym idzie jaka jest kolejna litera klucza. Postępując w ten sposób możemy odtworzyć cały klucz i odczytać wiadomość. Oczywiście nie zawsze otrzymana tabela częstości będzie dokładnie odpowiadała znanej statystyce. Czasami będziemy musieli wykonać wiele prób metodą wyszukiwania wyczerpującego aby odnaleźć właściwą literę klucza. Tym niemniej, próbować należy oczywiście w kolejności jak najlepszego dopasowania częstości. Jeżeli trudno jest dopasować tablicę częstości dla niektórych liter klucza, można przeprowadzić wstępną analizę częściowo odczytanego tekstu poszukując najczęstszych związków liter w języku angielskim, a w szczególności takich słów jak the, itp. Osobnym problemem jest automatyczne sprawdzanie, czy udało się nam poprawnie odszyfrować tekst. Dobrym pomysłem jest spróbować go „przeczytać”, tzn. pociąć go tak na fragmenty, aby następujące po sobie części były poprawnymi słowami. Do analizy należy oczywiście wykorzystać listę słów języka angielskiego, która jest udostępniona na stronie [2]. Do efektywnego wyszukiwania w słowniku można wykorzystać dowolne własne rozwiązania bądź gotowy kod źródłowy przeznaczony do obsługi słownika dostępny razem z artykułem [3]. Często bieżący fragment tekstu można podzielić na słowa w różny sposób. Jeśli określoną liczbę liter można podzielić na więcej niż jeden sposób to oczywiście bez analizy gramatycznej, którą nie będziemy się zajmowali, nic więcej nie możemy zrobić. Często jednak nawet jeśli kilkanaście liter da się podzielić w alternatywny sposób to po jakimś czasie okaże się, że idąc tą drogą otrzymujemy dalej bełkot, trzeba się więc cofnąć i wybrać inny sposób podziału. Kolejnym poważnym problemem jest to, że w tekście mogą się pojawiać słowa, których nie ma w słowniku. Mogą to być np. nazwy własne. Jedyną metodą jest wtedy opuszczenie pewnej liczby liter odgadując w jakiś sposób ile należy opuścić. Na stronie [2] znajduje się przykładowy program szyfrujący i deszyfrujący algorytmem Vigenère’a, a także prosty filtr, który przygotowuje tekst do postaci, którą akceptuje program, a więc usuwający wszystkie znaki różne od liter i zamieniający małe litery na wielkie. Na stronie znajduje się również zestaw zaszyfrowanych tekstów, które należy odszyfrować. Stopień trudności zadań jest zróżnicowany, a mianowicie są dostępne teksty zaszyfrowane bardzo prostymi i krótkimi kluczami oraz z kluczami dużo dłuższymi. Teksty różnią się także długością. Oczywiście im krótszy tekst tym trudniej jest go odczytać, gdyż mniej regularności możemy w nim znaleźć i mniej dokładne są zbudowane tablice częstości. Celem jest napisanie programu, który byłby w stanie łamać szyfr Vigenère’a. Na wyjściu programu powinien pojawić się tekst z podziałem na słowa. Jeżeli jest więcej niż jeden sposób podziału to można wyprowadzić dowolny z nich. Literatura [1] S. Singh, „Księga szyfrów”, Wydawnictwo Albatros A. Kuryłowicz, Warszawa 2001. [2] http://www-zo.iinf.polsl.gliwice.pl/˜sdeor/students.htm [3] M. Ciura, S. Deorowicz, „How to squeeze a lexicon”, Software-Practice and Experience, 2001; 31(11):1077–1090. http://www-zo.iinf.polsl.gliwice.pl/˜sdeor/pub/cd00abs.htm 4