Kilka razy już wspominałem o HMAC. Tym razem (czekając aż w końcu mi się Solaris 10 rozpakuje) napiszę kilka słów na temat wykorzystania tego algorytmu w celu zapewnienia integralności i źródła pochodzenia pliku.
(FoX - czy to podpada pod "techniczny"?)
Na początek krótkie zarysowanie sytuacji. W mojej pracy spotkałem się w trakcie konsultacji kilkukrotnie z następującym problemem:
- Jest sobie usługa/program generujący pewien plik wyjściowy,
- Plik jest przesyłany na jakiś serwer pośredni,
- Plik jest pobierany z serwera pośredniego przez inny program/usługę,
- Dane zawarte w pliku są wykorzystywane jako dane źródłowe,
Pojawia się problem, jak zapewnić integralność i autentyczność pliku. Jeśli chodziłoby tylko o integralność, wówczas zwykły hash wygenerowany przy pomocy praktycznie dowolnej funkcji skrótu. Na dobrą sprawę wystarczyłoby nawet jakieś prymitywne CRC. Ewentualny błąd w transmisji danych byłby łatwy do wykrycia (kod CRC lub hash po prostu by się nie zgadzał). Trochę gorzej przedstawia się sytuacja w przypadku, gdy podejrzewamy, że ktoś może celowo zmodyfikować plik na serwerze pośrednim. Tutaj kod CRC nie ma zastosowania, ponieważ zbyt łatwo jest wygenerować dwie różne wiadomości posiadające tą samą wartość CRC. Trochę lepiej przedstawia się sytuacja w przypadku funkcji skrótu, choć na przykład MD5 z uwagi na relatywną łatwość generowania kolizji już się tak bardzo dobrze do tej roli nie nadaje (podobnie zresztą SHA1, choć jest w trochę lepszej sytuacji). Tak naprawdę jednak wcale nie trzeba sięgać po tak abstrakcyjne pojęcia jak kolizje funkcji skrótu, by udowodnić, że zastosowanie tychże w opisywanym scenariuszu mija się z celem. Dlaczego? Trzeba jakoś przekazać hash wygenerowanego pliku, a nie istnieje inny kanał komunikacyjny między usługą źródłową i docelową, niż serwer pośredni, któremu nie ufamy. Jeśli przekazany za jego pośrednictwem zostanie również plik z sumą kontrolną (hashem), to zakładanie, że atakujący zmieni tylko plik, a nie ten plik kontrolny jest co najmniej naiwnością. W takim scenariuszu aż prosi się, by użyć kryptografii asymetrycznej, by plik był podpisywany przez usługę źródłową, a przed wykorzystaniem weryfikowany przez usługę docelową. Aż się prosi, ale... ale z pewnym zdziwieniem zauważyłem, że temat kryptografii asymetrycznej jest dziwnie przerażający, myśl o implementacji (jakiej implementacji, wykorzystaniu istniejących bibliotek) przeraża osoby zaangażowane w projekt i bardzo chcą usłyszeć o innym rozwiązaniu.
Innym rozwiązaniem może być wykorzystanie HMAC. Nie ma tutaj tej przerażającej kryptografii asymetrycznej, a w opisywanym przypadku (istnieje niewielka ilość "współpracujących" ze sobą usług) wykorzystanie tego rozwiązania jest w miarę wygodne. (O, rozpakował mi się Solaris, puszczę jego instalację w VirtualPC) HMAC jest właściwie funkcją skrótu, przy czym dodatkowo wykorzystywany jest pewien klucz, który powinien być znany tylko osobie generującemu "podpis" oraz osobie, która weryfikuje dane. Wynikowy kod zależy nie tylko od zawartości pliku (jak zwykły hash lub kod CRC), lecz również od użytego hasła. W rezultacie jeśli odbiorca weryfikuję wiadomość przy pomocy HMAC i weryfikacja kończy się sukcesem, można założyć, że plik nie uległ modyfikacji, ponieważ zgadza się kod HMAC, oraz, że kod został wygenerowany przez osobę znającą klucz, czyli w założeniu przez uprawnionego nadawcę. Teraz nawet jeśli plik jest kopiowany na niezaufany serwer (zarówno "plik główny" jak i plik zawierający odpowiedni kod HMAC), osoba, która kontroluje ten serwer i chce zmodyfikować plik, nie jest w stanie wygenerować odpowiedniego kodu HMAC, ponieważ nie zna klucza. Odbiorca otrzymując podstawiony plik natomiast łatwo taką modyfikację stwierdzi...
...i to by było na tyle jeśli chodzi o chytry pomysł wykorzystania HMAC zamiast podpisu cyfrowego. Pomysł wcale nie jest taki chytry, bo w końcu w znacznym stopniu po to właśnie HMAC powstał...