• Port MD5 dla AmigaOS 4.1

22.10.2011 17:47, autor artykułu: alekc
odsłon: 3438, powiększ obrazki, wersja do wydruku,

CodebenchW PPA#1 opisano algorytm CRC32. Widząc dopiero zapowiedź tego artykułu jeszcze przed wydaniem numeru napotkałem na podobny problem. Otóż okazało się, że na mojej SAM440 świetnie "ściąga się" i wypala obrazy ISO (Update 1 dla AmigaOS 4.1, aktualizacje Uboot), ale nie bardzo jest jak sprawdzić ich integralność po zakończeniu operacji pobierania. Problem o tyle istotny, że OWB do dzisiaj nie dorobiło się paska postępu (na szczęście AmigaOS 4.1 sam aktualizuje wyświetlane foldery oraz objętość RAM dysku). Dodatkowo obrazy ISO z dystrybucjami Linuksa dla SAM zazwyczaj posiadają plik [nazwa_iso].md5, więc głupotą byłaby próba instalacji takiego systemu bez sprawdzenia czy obraz jest poprawny. W ten oto sposób nadarzyła się okazja do szybkiego przetestowania SDK dostarczanego przez firmę Hyperion.

Dlaczego nie CRC32?

Powodów jest kilka. Pierwszy to fakt, że dla obrazów ISO z dystrybucjami Linuksa sumy kontrolne są liczone w MD5. Stan taki ma swoją przyczynę. Podłożem problemu algorytmów z rodziny CRC jest fakt, iż nie dają one odpowiedniej pewności co do integralności kontrolowanego obiektu (wiadomości). Mówiąc już bardziej technicznie - nie są one kryptograficznie silne. MD5 z kolei należy do kryptograficznych, jednokierunkowych funkcji skrótu. Oznacza to w teorii, że:

1. zmiana jednego bitu w wiadomości powoduje inny wyniki funkcji

2. nie ma dwóch różnych wiadomości dających taki sam wynik funkcji

3. z wyniku funkcji nie można odczytać lub wydedukować wiadomości, która została użyta jako wejście

4. ta sama wiadomość zawsze da taki sam wynik.

W praktyce charakterystyka z punktu drugiego nazywana jest brakiem kolizji. Jak się okazuje MD5 ma jednak kolizję. To jeden z powodów, dla którego od kilku lat zaleca się zastępowaniem jej silniejszymi funkcjami skrótu, np. z rodziny SHA. Na nasze potrzeby wady MD5 nie mają jednak aż tak dużego wpływu i dlatego przy niej pozostaniemy.

Z perspektywy teorii bezpieczeństwa informacji CRC32 ma kilka wad, o których warto wspomnieć w kontekście MD5. Nawet jeśli użyjemy najdłuższego standardowego wielomianu 65-bitowego (CRC64), nadal pozostaje problem wykrywania określonych zmian. Sumy kontrolne zostały wymyślne do wykrywania typowych błędów w transmisji danych, a ich zadaniem była szybka kontrola komunikatu. Oznacza to, że wiadomość można tak zmodyfikować, aby jej suma kontrolna pozostała bez zmian. Dlatego do kontroli obrazów ISO czy pamięci, MD5 lub mocniejsze funkcje skrótu nadają się znacznie lepiej.

Różne cele twórców algorytmów CRC i MD (MD5 jest jednym z rodziny funkcji, wcześniejsza jej wersja nazywała się MD4) mają odzwierciedlenie w ich konstrukcji. MD5 nie jest oparta o wielomian, pod który podstawia się kolejne bity wiadomości. Cała wiadomość jest dzielona na równe, 512-bitowe bloki + ostatni blok o długości 448 bitów. Bloki są uzupełniane za pomocą zer do wymaganego rozmiaru. Różnica w rozmiarze ostatniego bloku wynika z faktu tworzenia miejsca na 64-bitowy licznik oznaczający rozmiar wiadomości. W ten sposób wszystkie bloki wiadomości mają jednakową długość 512 bitów. Każdy blok przechodzi transformację, która składa się na wynik końcowy. Zainteresowanych kryptografią odsyłam do Wikipedii gdzie znajduje się dokładniejszy opis algorytmu MD5.

"Portujemy" md5.c

Gdy stanąłem przed problemem weryfikacji obrazu ISO, sięgnąłem do zasobów OS4Depot i stwierdziłem, że hasło "md5" zwraca zero wyników. Drugim adresem był Aminet i tutaj znalazłem 8 pakietów, z czego najnowszy był z 2000 roku (generator liczb pseudolosowych na bazie MD5 dla 68k i PPC). Ciekawą opcją wydała się wersja dla Arexxa, ale idąc tym tropem równie dobrze mógłbym skorzystać z wbudowanej w AmigaOS 4.1 wersji Pythona. Pakietów dla PPC i wersji nowszej niż 4.0 dla AmigaOS nie znalazłem. Postanowiłem zatem w pełni wykorzystać dostępne mechanizmy i aplikacje w wersji 4.1 systemu.

Pierwszym krokiem była instalacja oficjalnego SDK. SDK można bezpłatnie pobrać ze strony firmy Hyperion - w momencie pisania tego artykułu najnowsza publicznie dostępna wersja była oznaczona numerem 53.20 z 1 marca 2010 roku. Ponieważ jest to wersja sprzed Update 2, to pewnie w momencie czytania tego tekstu będzie dostępna nowsza wersja.

Instalacja SDK przebiega prosto. Po rozpakowaniu archiwum uruchamiany program instalacyjny i klikamy w "Next". Następnie wykonujemy jeszcze restart (choć można obyć się bez niego - szczegóły znajdziecie w dokumentacji SDK). Program instalacyjny domyślnie zakłada przypisania SDK:. Po restarcie możemy sprawdzić czy wszystko działa. W tym celu uruchamiany kompilator GCC z przełącznikiem "-version". Jeśli GCC się uruchomiło, to znaczy że kompilator działa. Nie spotkałem się z problemami podczas instalacji SDK na czystym systemie, więc niewiele mogę powiedzieć o potencjalnych pułapkach. Natomiast podczas aktualizacji lub usuwania SDK należy uważać i pamiętać o tym, aby usunąć wpisy dodane przez program instalacyjny do Startup-Sequence i User-Startup.

CodebenchTeraz możemy utworzyć plik hello.c:

#include <stdio.h>

void main()

{

printf(„Hello world”);

}

Lub jeśli wolimy c++ (wtedy plik zgodnie z przyjętymi konwencjami powinien nazywać się hello.cpp):

#include <iostream.h>

void main()

{

cout << “Hello world”;

}

Do utworzenia pliku w zupełności wystarczy systemowy Notepad. Po jego zapisaniu w katalogu, w którym znajduje się plik wydajemy polecenie:

gcc -o hello hello.c

lub

gcc -o hello hello.cpp

w zależności od wersji dialektu, który wybraliśmy. Przełącznik "-o" definiuje nazwę pliku wykonywalnego, który zostanie utworzony na podstawie kompilacji plików źródłowych. Domyślnie gcc tworzy plik wynikowy o nazwie a.out. W przypadku AmigaOS 4.x kompilator tworzy pliki w formacie ELF a nie HUNK, jak ma to miejsce w przypadku wcześniejszych wersji systemu. Warto o tym pamiętać, ponieważ pakiet bintools poprawnie obsługuje pliki wynikowe AmigaOS 4.x. Dzięki temu możemy na przykład korzystać z narzędzia objdump, które jest dołączone do oficjalnego SDK.

Pobieramy plik źródłowy z adresu:

http://people.csail.mit.edu/rivest/Md5.c

i zapisujemy go na dysku. Teraz możemy skompilować nasz "port" md5.c wydając polecenie:

gcc -o md5 Md5.c

pod warunkiem, że znajdujemy się w tym samym katalogu, w którym zapisaliśmy kod źródłowy. Do pierwszych prób idealnie nadaje się mechanizm RAM dysku. Jeśli wszystko pójdzie dobrze, powinniśmy otrzymać plik wynikowy md5, który jest gotowy do użycia.

Inne strategie portowania

Do tej pory korzystaliśmy tylko z narzędzi z oficjalnego SDK. Do tak małego projektu, który składa się z jednego pliku źródłowego, wykorzystanie samego SDK ma dużo sensu. W przypadku bardziej złożonych projektów oczywiście można pisać pliki makefile i używać ich do kompilacji, jednak na dłuższą metę jest to rozwiązanie mało wygodne. Dlatego możemy wybrać dwie strategie:

- wykorzystanie środowiska IDE na platformie AmigaOS,

- wykorzystanie cross kompilatorów na innych platformach.

Opcja druga daje szerokie możliwości i wygodę pracy (zwłaszcza jeśli ktoś tworzy przede wszystkim na inne platformy, a Amiga jest platformą mniej ważną). Można wykorzystać omawiany w poprzednim numerze PPA, AmiDevCPP na platformie Windows. Dla systemów Unix, Linux, BSD dostępne są cross kompilatory, z czego najlepsze doświadczenia miałem z tymi bazującymi na gcc. Pakiet z którym najlepiej mi się pracowało na OpenBSD został przygotowany przez Joachima "Zerohero" Birginga i jest dostępny pod adresem: http://www.zerohero.se/cross/os4.html

Wybór AmigaOS jak platformy deweloperskiej stawia nas przed wyborem: Cubic IDE lub CodeBench. Oba pakiety potrzebują oficjalnego SDK. Teoretycznie można na AmigaOS 4.x uruchomić jeszcze StormC PPC, ale w moim przypadku pakiet ten na AmigaOS 4.1 nigdy nie działał stabilnie.

Cubic IDE wymaga obecności SDK w wersji 51.22. Idealnie jest najpierw zainstalować Cubic IDE a potem SDK [3]. Rozmowy z twórcą pakietu pozwoliły potwierdzić, że działa on poprawnie z nowszymi wersjami SDK, ale nadal jest wymagana instalacja wersji 51.22 SDK. Niestety Hyperion Entertainment na swojej stronie, w momencie pisania artykułu, udostępniał ze starych wersji tylko 53.13.

CodeBench nie był dostępny w pełnej, komercyjnej wersji w trakcie pisania tego tekstu. Chwilami przypomina on StormC PPC, co dla użytkowników tego produktu firmy Haage&Partners może być zaletą. Z drugiej strony inna filozofia działania niż w przypadku CubicIDE nie każdemu musi odpowiadać. Dlatego najlepszym rozwiązaniem jest pobranie wersji demo obu pakietów i ich samodzielne porównanie.

Do dalszej pracy będziemy używać CodeBench, ponieważ obecna wersja pracuje poprawnie z aktualnym SDK 53.20. Aby wygodnie edytować kod, musimy najpierw utworzyć projekt. W tym celu wybieramy z CodeBench ToolBar przycisk "Create new project" (żółty sześcian po lewej stronie). W oknie "Project information" wpisujemy następujące elementy:

W zakładce General:

Project name (czyli nazwa projektu) - wpisujemy: MD5,

Project base directory (czyli lokalizacja katalogu, który będzie zawierał nasze pliki)

W zakładce Make zaznaczamy opcję "Create Makefile".

W zakładce Linker, w polu "Executable name" ustawiamy nazwę pliku wynikowego, np. cbmd5.

W oknie Project... dodajemy do pozycji "Source files" nasz plik Md5.c. Teraz zapisujemy projekt i możemy pracować dalej. Podczas pierwszej kompilacji moją uwagę zwróciło ostatnie ostrzeżenie dotyczące wyniku zwracanego przez funkcję main(). Poprawmy ten problem. W tym celu w kodzie źródłowym należy dokonać kilku zmian. Najpierw odszukaj funkcję main() - jest ona na końcu pliku. W jej definicji należy usunąć słowo kluczowe void i zastąpić je słowem kluczowym int. Teraz definicja funkcji wygląda tak:

int main( argc, argv)

int argc;

char *argv[];

Następnie w ostatniej linijce kodu funkcji main() dodajemy kod:

return(0);

i zapisujemy kod źródłowy na dysk. W oknie "Build window" wybieramy opcję "Build whole Project", co spowoduje skompilowanie wszystkich plików projektu (w naszym przypadku jest to oczywiście tylko jeden plik). Teraz warto się przyjrzeć jeszcze wewnętrznej budowie programu. W oknie "Quick Links" mamy pokazane niektóre funkcje. Jak widać brakuje main() oraz kilku innych funkcji - jest to jeden z elementów do poprawy w kolejnych wersjach CodeBench. Oto kilka istotnych funkcji:

MDString () - wylicza funkcję skrótu dla danej wiadomości przekazanej jako parametr

MDTestSuit() - testuje poprawność algorytmu na znanych wiadomościach oraz zakodowanych poprawnych wartościach funkcji skrótu dla nich

MD5Init() - inicjalizuje funkcję skrótu (bez wywołania tej funkcji algorytm nie będzie działał poprawnie)

Transform() - razem z makrodefinicjami serce algorytmu MD5 (tutaj zaimplementowane są wszystkie 4 rundy przekształcenia, które decydują o sile MD5)

Odnośniki

Cubic IDE http://devplex.awardspace.biz/

CodeBench http://www.codebench.co.uk/

Installing the latest OS4 SDK in Cubic IDE http://www.amigans.net/modules/AMS/article.php?storyid=30

Artykuł oryginalnie pojawił się w trzecim numerze Polskiego Pisma Amigowego.

 głosów: 1   
dodaj komentarz
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem