Jakub Lutyński 4T2 Paweł Podkalicki 4T2 Andrzej Zaleski 4T2 Michał Wilkowski Warszawa, 27.01.2008 r Układy cyfrowe - Algorytm Twofish 1. Opis projektu Celem naszego projektu będzie zrealizowanie układu cyfrowego zdolnego do szyfrowania danych algorytmem Twofish. Algorytm ten zostanie zrealizowany na układzie programowalnym Cyclone EP2C35F672C8. Układ będzie się komunikować z komputerem poprzez moduł USB FTDI. Do opisu projektowanego układu uŝyjemy języka VHDL, a narzędziem CAD za pomocą, którego zamierzamy zrealizować projekt jest program Quartus firmy Altera. 2. Opis algorytmu Twofish: Algorytm Twofish jest jednym z pięciu algorytmów zakwalifikowanych do finału konkursu AES Advanced Encryption Standard. Pomimo, Ŝe nie został laureatem wyselekcjonowanym do standaryzacji, jest uznawany za algorytm bezpieczny i szybki. Zbudowany na zasadzie prawie czystej sieci Feistela, jest powiązany z wcześniej powstałym szyfrem blokowym Blowfish. Twofish jest standardem otwartym, nie objętym Ŝadnymi patentami i do tej pory ( luty 2007) nie został złamany poza metodą ataku brute force. W kryptografii Twofish jest symetrycznym, blokowym kluczem szyfrującym. Operuje na blokach danych o wielkości 128 bitów i wykorzystuje klucze wielkości od 128 do 256 bitów. Najczęściej są stosowane klucze o długości 128, 192 oraz 256 bitów. Cechą charakterystyczną Twofish'a jest zastosowanie kluczujących S-boxów. Blok danych wejściowych o długości 128 bitów dzielony jest na cztery części, z których kaŝda złoŝona z 32 bitów jest poddawana operacji whiteninigu { tzn. wykonaniu XOR-owania pomiędzy czterema blokami danych (po 32 bity kaŝdy) z czterema kluczami ( takŝe o długości 32 bity kaŝdy). Powoduje to zwiększenie siły algorytmu i utrudnienie złamania go}. Następnie dwie pierwsze części (R 0 i R 1 ) trafiają do funkcji F. Kolejne części (R 2 i R 3 ) są pozostawiane bez zmian. Funkcja F bierze dwie pierwsze części oraz dwa klucze(metoda tworzenia kluczy będzie opisana w osobnej sekcji) i na ich podstawie generuje dwa wektory składające się w sumie z 64 bitów. Wektory te są dalej łączone z wektorami R 2 i R 3, XOR-owane z dwoma innymi kluczami oraz przesuwane bitowo w prawą lub lewą stronę. Kolejnym etapem jest zamiana miejscami pary wektorów R0 i R1 z parą R2 i R3 oraz ponowne przejście przez funkcję F. Takie jedno wykonanie się funkcji F wraz z późniejszymi
operacjami na jej wynikach oraz zamianie miejscami par wektorów jest określane mianem rundy algorytmu. Na cały algorytm Twofish składa się 16 takich rund. W kaŝdej z nich do funkcji F trafiają inne klucze funkcja F jest najwaŝniejszym elementem sercem algorytmu. Po wykonaniu ostatniej, 16 rundy bloki R są ponownie XOR-owane z kluczami i podawane na wyjście jako zaszyfrowane bloki danych. Sieć Feistela Sieć Feistela pozwala na szyfrowanie i deszyfrowanie informacji tym samym algorytmem, mimo iŝ funkcja f nie jest odwracalna. Sieć Feistela generuje z tekstu jawnego szyfrogram, a z szyfrogramu tekst jawny. W ten sposób konstruowanie algorytmów szyfrujących znacznie się uprościło, poniewaŝ nie trzeba się troszczyć o odwracalność funkcji f. Pomysł jest bardzo prosty. Tekst jawny dzieli się na dwa równe bloki Li Ri. Funkcja f jest właściwym algorytmem szyfrującym. Jako wynik otrzymuje się szyfrogram. i - jest numerem kolejnej rundy. To oznacza, iŝ wynik szyfrowania jest ponownie i-krotnie szyfrowany, co polepsza jakość szyfrowania. Struktura ta jest wykorzystywana w teorii szyfrów blokowych od dawna i została gruntownie przebadana pod kątem bezpieczeństwa. S-box: S-box (z ang. Substitution Box) jest podstawową częścią algorytmu wielu współczesnych szyfrów, rodzaj czarnej skrzynki z wejściem, wyjściem i niewiadomą zawartością. Istota jego działania polega na podstawieniu określonego bitu (lub ciągu bitów) innym, w zaleŝności od bitów : poprzedzającego i następującego. Wartości umieszczone w S-boksie mają krytyczny wpływ na bezpieczeństwo szyfru. Funkcja F: Funkcja F jest sercem algorytmu Twofish. Jej działanie oparte jest w duŝej mierze na innej funkcji,
zwanej funkcją G. Dwa bloki danych podawane są do dwóch działających równolegle funkcji G. Wyjścia tych funkcji (po 32 bity) są następnie przekazywane do bloku PHT, gdzie następuje ich przemieszanie są sumowane modulo 2 ze sobą, a dokładniej a ' = (a + b) mod 2 32 b ' = (a + 2b) mod 2 32 gdzie a jest wyjściem z pierwszej funkcji G, natomiast b jest wyjściem z drugiej funkcji G. Funkcja G ( i funkcja H) : Funkcja G to funkcja H, której wejściem jest blok danych i blok S generowany z klucza uŝytkownika( o bloku S napisaliśmy przy okazji opisu sposobu generacji podkluczy). Do funkcji H jest kierowany blok danych wejściowych X o długości 32 bitów. Blok ten jest dzielony na 4 równe części. KaŜda z nich trafia na permutację p 0 lub p 1. W wyniku działania tej permutacji blok danych zamieniany jest w ściśle ustalony sposób na inny blok. Następnie wynik działania 4 takich permutacji (po 1 dla kaŝdej części słowa X) poddawany jest operacji XOR z drugim argumentem funkcji H ( dla funkcji G jest to słowo S). Potem wynik tego XOR'a jest ponownie dzielony na 4 części i kaŝda z nich trafia na kolejne permutacje. Sytuacji taka powtarza się kilkukrotnie, w zaleŝności od długości klucza uŝytkownika: 128 bitów - 3 krotnie 192 bity - 4 krotnie 256 bitów - 5 krotnie Gdy zakończy się działanie wszystkich tych permutacji wynik trafia do macierzy MDS, która zwraca w wyniku inny ciąg bitów. Jest on wynikiem działania funkcji H ( i/lub G ). Generacja podkluczy: Twofish działa na podstawie klucza podawanego przez uŝytkownika. Klucz ten dzielony jest na bajty, ilość tych bajtów zaleŝy ściśle od długości klucza i wynosi 16, 24 lub 32 bajty dla kluczy odpowiednio 128, 192 lub 256 bitowych. Na podstawie tych bajtów tworzone są słowa M i, będzie ich 2k, gdzie k = N/64 (N - długość klucza w bitach). Z tych słów tworzone są dwa wektory M e oraz M o, przy czym pierwszy z nich zawiera ułoŝone kolejno słowa M i dla i parzystych, zaś drugi dla i nieparzystych. Ponadto z klucza uŝytkownika generowany jest takŝe wektor S, który jest potem potrzebny, aby wykonać funkcję G (ściślej mówiąc, funkcja G definiowana jest jako funkcja H, której drugim argumentem jest właśnie wektor S). Wektor ten powstaje z przemnoŝenia 8- bajtowych grup klucza przez macierz RS. Macierze RS i MDS: Macierze MDS oraz RS słuŝą do przemieszania bitów wejściowych w sposób znakomicie utrudniający późniejsze złamanie algorytmu. Macierz MDS słuŝy do pomnoŝenia przez nią 4 bajtów słowa wejściowego. Elementami macierzy
MDS są wyłącznie liczby (5B) 16, (EF) 16 lub (01) 16. MnoŜenie poszczególnych bajtów przez tą macierz, a takŝe wszystkie operacje dodawania wykonywane podczas tego mnoŝenia są wykonywane w ciele Galois nad przestrzenią 2 8. Wielomianem pierwotnym tej przestrzeni dla macierzy MDS jest wielomian: v(x) = x 8 + x 6 + x 5 + x 3 + 1. O ile podczas dodawania zapewnienie prawidłowego wyniku (czyli wyniku, który będzie znajdował się w ciele Galois) jest proste, poniewaŝ jest to tylko XOR'owanie odpowiednich bitów, o tyle mnoŝenie w ciele GF(256) jest nieco bardziej skomplikowane. Sprawę uprasza fakt, Ŝe mnoŝenie odbywa się tylko przez trzy róŝne liczby. Jednak podczas mnoŝenia trzeba juŝ upewnić się, czy wynik znajduje się jeszcze w ciele Galois, czyli trzeba go podzielić przez wskazany wyŝej wielomian pierwotny. Macierz RS działa na zasadzie identycznej jak macierz MDS, z tą róŝnicą, Ŝe na wejściu znajduje się 8 bajtów a nie 4 jak było w przypadku MDS. W tym przypadku mnoŝenie takŝe odbywa się w Ciele GF(256), jednak inny jest wielomian charakterystyczny niŝ w przypadku macierzy MDS. Wielomian ten to: v(x) = x 8 + x 6 + x 3 + x 2 + 1. Zalety algorytmu Twofish: Do głównych zalet algorytmu Twofish naleŝy zaliczyć bezpieczeństwo algorytm do dziś nie został złamany, oraz fakt, Ŝe nie został laureatem AES mniej wykorzystywany, a co za tym idzie mniej naraŝony na próby złamania
Budowa schematu blokowego Ogólny schemat układu Data_in - wejście danych Wejścia sterujące: key - stan wysoki oznacza, Ŝe układ pracuje w trybie generowania kluczy encr/decr - szyfrowanie/deszyfrowanie - stan wysoki oznacza szyfrowanie reset - stan wysoki przerywa przetwarzanie danych clock - zegar Data_out - wyjście danych busy - sygnał generowany przez układ. Stan wysoki oznacza, Ŝe układ przetwarza dane. Budowa układu blok K - XORowanie z odpowiednim kluczem; w kaŝdym bloku z innym blok p-x-p - blok, w którym będzie realizowana kombinacja przesunięcia bitowego i XORowania z wyjściem bloku funkcji F w zaleŝności od gałęzi i trybu pracy
Budowa bloku funkcji F PHT - realizacja pseudo - transformaty Hadamarda dwóch sygnałów blok K - XORowanie z odpowiednim kluczem; w zaleŝności od numeru rundy Budowa bloku funkcji g Ten blok realizuje S-boxy. q0, q1 - permutacje wektorów blok S - XORowanie z odpowiednimi (róŝnymi kluczami) blok MDS - mnoŝenie przez macierz MDS
CZĘŚĆ II - dokumentacja po implementacji układu w VHDL. 1. Zmiany i uzupełnienia projektowe Jednostka zostanie zrealizowana w postaci automatu synchronicznego, mogącego w jednym stanie jednocześnie wykonywać tylko jedną z operacji kombinacyjnych. Takie podejście pozwala nam na uŝycie tych samych bloków funkcjonalnych (np. permutacji, rotacji, xorowania, whitenningu ) w operacjach wykonywanych w poszczególnych stanach i co za tym idzie oszczędne wykorzystanie zasobów programowalnego układu cyfrowego. Przyjęty przez nas model współpracy automatów jest sekwencyjny. (Dokumentacja dotyczy układu szyfrującego z kluczem 128 bitowym.) Zmiana w interfejsie: dodany został sygnał wejściowy ukl sygnał zezwolenia, odpowiednik enable Wejścia i wyjścia układu Nazwa Typ Rozmiar Krótki opis clk IN 1 bit Zegar sterujący układem rst IN 1 bit Reset asynchroniczny key IN 1 bit Sygnalizuje wejście klucza lub tekstu jawnego ukl IN 1 bit Sygnał zezwolenia encr IN 1 bit Gdy = 1 szyfrowanie, gdy = 0 - deszyfrowanie data_in IN 128bit Wejściowy blok danych busy OUT 1 bit Sygnalizacja zajętości data_out OUT 128 bit Wyjściowy zaszyfrowany/zdeszyfrowany blok danych Wejścia (sterujące układem): clk układ jest sterowany automatem synchronicznym, którego zegar clk moŝe być taktowany z maksymalną częstotliwością MHz. rst wejście resetu asynchronicznego. Stan wysoki tego wejścia występuje podczas narastającego zbocza zegara.
key wejście sygnalizujące czy blok danych wejściowych (data_in) ma być odbierany przez układ jako klucz ( key = 1 ) czy jako tekst jawny ( key = 0 ) ukl wejście zezwalające na szyfrowanie/deszyfrowanie układem. Gdy ukl = 0 to układ nie wykonuje szyfrowania/deszyfrowanie, w przeciwnym przypadku(ukl = 1 ) operacje te mogą być wykonywane. encr określa tryb pracy układu. Gdy encr = 1 to następuje szyfrowanie, w przeciwnym przypadku deszyfrowanie. Wejście: Wyjście: data_in 128 bitowy blok danych wejściowych, który jest odpowiednio szyfrowany lub deszyfrowany przez układ. busy sygnalizuje, Ŝe automat wykonuje pracę. Gdy jest zmiana na zbocze opadające dane są wyprowadzane na wyjście. data_out 128 bitowy blok danych wyjściowych, po szyfrowaniu/deszyfrowaniu. 2. Automat stanów Opis stanów automatu: Idle stan bezczynny Kgenrob generacja kluczy roboczych ( robocze klucze to Me, Mo, S ) Kgen_01, kgen_23 - generacja 4 podkluczy uŝywanych przy whitenningu na wejściu (2 osobne stany) Kgen_45, kgen_67 - generacja 4 podkluczy uŝywanych przy whitenningu na wyjściu (2 osobne stany) In_whit whitenning wejściowy round_01, round_02,..., round_15, round_16 stany szyfrowania /deszyfrowania w zaleŝności od sygnału encr zrealizowane w 16 rundach out_whit whitenning wyjściowy W sumie automat do obsługi algorytmu Twofish jest zrealizowany na 24 stanach.
3. Synteza układu Syntezę projektu przeprowadziliśmy na układzie Cyclone II EP2C35F672C6 dla kilku wbudowanych w Quartus metod kodowania automatu stanów: Auto One - Hot Minimal bits Grey Dla kaŝdej z powyŝszych metod kodowania stanów układ został zsyntezowany trybami optymalizacji: Balanced Speed Area Projekt dla po syntezie poszczególnymi metodami kodowania automatu stanów i dla poszczególnych trybów optymalizacji ma następujące parametry po kompilacji : (w nawiasach podano procent zajętości układu) AUTO: Tryb Syntezy Total Logic Elements Total Combinational Functions Dedicated Logic Registers ŚcieŜka Krytyczna [ns] CLK [MHz] Speed 3573 (11%) 3147(9%) 856(3%) 24,94 40,09 Balanced 3700 (11%) 3352(10%) 856(3%) 26,48 39,76 Area 3678(11%) 3348(10%) 856(3%) 24,41 40,96 ONE HOT: Tryb Syntezy Total Logic Elements Total Combinational Functions Dedicated Logic Registers ŚcieŜka Krytyczna [ns] CLK [MHz] Speed 3573(11%) 3147(9%) 856(3%) 24,94 40,09 Balanced 3700(11 %) 3352(10%) 856 (3%) 26,48 39,76 Area 3678(11%) 3348(10%) 856(3%) 24,41 40,96 MINIMAL-BITS: Tryb Syntezy Total Logic Elements Total Combinational Functions Dedicated Logic Registers ŚcieŜka Krytyczna [ns] CLK [MHz] Speed 3598(11%) 3167(10%) 837(3%) 25,58 39,09 Balanced 3681(11%) 3367(10%) 837(3%) 25,41 39,34 Area 3689(11%) 3364(10%) 837(3%) 25,63 39.01
GREY: Wnioski: Tryb Syntezy Total Logic Elements Total Combinational Functions Dedicated Logic Registers ŚcieŜka Krytyczna [ns] CLK [MHz] Speed 3600(11%) 3183(10%) 837 25,46 39,27 Balanced 3727(11%) 3401(10%) 837 25,41 39,36 Area 3738(11%) 3406(10%) 837 26,20 38,17 Parametry kompilacji dla metod kodowania stanów AUTO i HOT-ONE są identyczne. Jest to najprawdopodobniej efekt domyślnego doboru metody kodowania (AUTO) przez Quartusa jako metody HOT-ONE Z pośród wszystkich dostępnych metod kodowania automatu najlepsza okazała się metoda HOT-ONE, przy optymalizacji syntezy w trybie speed, dla którego układ zajmował najmniej elementów logicznych oraz miał względnie dobre parametry czasowe. System Quartus, zatem wybiera w trybie AUTO najbardziej optymalną metodę kodowania automatu stanów. 4. Symulacja funkcjonalna: a) Szyfrowanie obraz przejścia układu przez poszczególne stany automatu:
PowyŜsze symulacje potwierdzają poprawność działania układu szyfrującego dla wektora testowego: I = 1 KEY = 00000000000000000000000000000000 PT = 00000000000000000000000000000000 CT = 9F589F5CF6122C32B6BFEC2F2AE8C35A KEY - klucz uŝytkownika PT - tekst jawny (plain text) CT - tekst zaszyfrowany (cipher text) oraz automatu, który przechodzi poprzez kolejne stany zgodnie z załoŝonym modelem teoretycznym. * Zaprezentowane powyŝej wykresy odnoszą się do symulacji funkcjonalnej przeprowadzonej dla poprzedniej wersji układu, która zwierała pomocnicze wyjście swyj do przechowywania wyników po whitenningach i po poszczególnych rundach, co było pomocne przy debugowaniu układu.
b) Deszyfrowanie (...) ( stany od rundy 2 do rundy 15 zostały pominięte na wykresach)
PowyŜsze symulacje potwierdzają poprawność działania układu w trybie deszyfrowania dla wektora testowego: I = 6 KEY = 6363977DE839486297E661C6C9D668EB PT = 816D5BD0FAE35342BF2A7412C246F752 CT = 5449ECA008FF5921155F598AF4CED4D0 c) szyfrowanie dowolnego wektora testowego: (wykresy nie pokazują pełnego przebiegu symulacji, poniewaŝ mają na celu zaprezentowanie jedynie poprawności działania układu)
(...) PowyŜsza symulacja obrazuje działanie układu dla wektora testowego i takŝe potwierdza poprawne działanie układu w trybie szyfrowania: I = 3 KEY = 9F589F5CF6122C32B6BFEC2F2AE8C35A PT = D491DB16E7B1C39E86CB086B789F5419 CT = 019F9809DE1711858FAAC3A3BA20FBC3 5. Testbench: Do testowania zaprojektowanego układu cyfrowego został napisany w VHDL u testbench generator testów z modułem kolekcjonującym zaszyfrowane odpowiedzi układu na wektory klucza i tekstu jawnego. Odpowiedzi te są porównywane z wektorem wzorcowym. Testbench wykonuje symulację, którą moŝna porównać do badania fizycznego układu, którego wejścia podłączamy do stymulatora (generatora testów) i obserwujemy wyjścia. Symulacja kodu VHDL, testbench jest
równoznaczna z wirtualnym eksperymentem, w którym fizyczny układ zastąpiono opisem VHDL. Symulację testbencha wykonaliśmy w środowisku Model Sim. Wektory klucza i tekstu jawnego pobierane w symulacji testbencha są zapisane w pliku test_vectors.txt. Format tego pliku to 3 ciągi znaków podawane bez przerw: Klucz - wartość klucza w notacji HEX Szyfrowanie/deszyfrowanie wartość w postaci bitowej podawana na wejście encr w automacie Tekstjawny/szyfrogram wartość w notacji HEX Testbench generuje wyniki dla poszczególnych symulacji i zapisuje je do pliku results.txt. Ponadto podczas wykonywania symulacji testbench porównuje wyniki szyfrowania/deszyfrowania z wektorami wzorcowymi, które wczytuje z pliku good_results.txt. Wyniki tych porównań są zapisywane do pliku checked.txt. Niestety wadą naszego testbencha jest moŝliwość przeprowadzenia symulacji testowej tylko dla jednej pary klucz/tekst. Niemniej jednak podmiana wektorów w plikach wejściowych daje dobre rezultaty. Materiały uŝyte w trakcie pisania projektu: 1. Twofish: A 128-Bit Block Cipher autorzy Bruce Schneier, John Kelsey, Doug Whiting, David Wagner, Chris Hall. Http://www.schneier.com/twofish.html Zawiera dokładną specyfikację algorytmu, jego kryptoanalizę, analizę wydajnościową oraz wektory testowe pozwalające sprawdzić dowolną implementację pod względem poprawności. 2. Twofish: A block Encryption Algorithm autorzy Bruce Schneier, John Kelsey, Doug Whiting, David Wagner, Chris Hall, Niels Ferguson Prezentacja przygotowana przez twórców algorytmu Twofish. 3. Synteza Układów Cyfrowych - autorzy: prof. Tadeusz Łuba, dr Mariusz Rawski, dr Paweł Tomaszewicz, dr Bogdan Zbierzchowski Materiały traktujące o projektowaniu układów cyfrowych, w tym przykładowa implementacja algorytmu DES oraz kilka informacji o języku VHDL 4. Implementation of the Twofish Cipher Using FPGA Devices - Pawel Chodowiec, Kris Gaj, Lipiec 1999; http://www.schneier.com/paper-twofish-fpga.html 5. Hardware Implementation of Twofish Block Cipher - Ranjeeta M. Patil, ECE 646 Project Report, George Mason University