Kojarzycie pewnie, czym są hasztagi? Albo haszysz, na przykład z Maroka?
Jeśli tak, to fajnie. Ale dzisiaj będzie o czymś zupełnie innym.

Hash (czyt. hasz) w znaczeniu komputerowym. Będę tu używał spolszczonego zapisu, bo jest dwuznaczny i kojarzy się z tym marokańskim znaczeniem :sunglasses:

Wydaje się czymś bardzo tajemniczym i niezrozumiałym. Ale jednocześnie to jeden z fundamentów współczesnej informatyki. W życiu codziennym sprawa jest prosta – haszy używa się do porównywania, czy dwie rzeczy są takie same. Nic mniej i nic więcej.

Sprawdzanie, czy wpisaliśmy prawidłowe hasło? Albo czy już jesteśmy w bazie danych? Blokowanie programów, do których mógł zostać dodany wirus? Podpisy cyfrowe? Kryptowaluty?
Za kulisami wszystkich tych rzeczy stoją hasze. Prosta rzecz o wielu zastosowaniach.

Hasz jest dla nas interesujący również z punktu widzenia prywatności.

Niedługo będę pisał o wredniejszych sposobach identyfikacji – skryptach, które analizują subtelne cechy przeglądarki i przypisują nam jakiś numer. A później porównują go ze swoją bazą, żeby nas rozpoznać w różnych zakątkach internetu. Hasz jest fundamentem ich działania.

Z tego względu warto go poznać, zanim przejdziemy dalej. Mogę Wam obiecać, że jeszcze nieraz będę odsyłał do tego wpisu.

Czym jest hasz?

Nie będę tu o nim pisał od strony technicznej, bo: a) wpis byłby długi i męczący; i b) sam nie pojmuję szczegółów, za dużo matmy. Ale znam wystarczająco wiele ogólników.

Bardziej oficjalną (ale wciąż w miarę przystępną) definicję znajdziecie na przykład na Wikipedii.

W praktyce haszowanie polega na tym, że mamy funkcję. Czyli fragment kodu. Kiedy użyjemy tej funkcji na jakichś danych, to je przetworzy i wypluje pewien ciąg znaków.
Nasza funkcja ma dwie kluczowe właściwości:

  • Póki wrzucamy w nią identyczne dane, otrzymujemy dokładnie taki sam ciąg znaków.
  • …Ale jeśli wrzucimy inne dane, to wypluje coś całkiem innego.

Jeśli jesteście wzrokowcami, to może lepiej to wyrazi mój bidny autorski schemat:

Schemat pokazujący parę przykładów tekstu poddawanych haszowaniu. Funkcja haszująca jest tu zobrazowana jako zsyp fabryczny.

Zwróćcie uwagę, że w dwóch przypadkach mamy napis Tekst, a w trzecim Text, przez iks. Ten sam tekst, poddany działaniu tej samej funkcji, daje ten sam wynik. Ale zmiana paru literek daje coś całkiem innego.
Napis SHA1 na zsypach to z kolei jedna z najpopularniejszych funkcji haszujących.

A jeśli chcecie przykład z kodem, to tutaj mam mały w języku Python:

Konsola interaktywna Pythona, linijka po linijce. Widać że po użyciu funkcji hash na tekście 'Ciemna strona' wyświetliło dwa razy taką samą długą liczbę. Ale kiedy użyto jej na tekście z literą 'o' zmienioną na '0', to liczba jest całkiem inna.

Wystarczyła zmiana jednej litery, żeby funkcja haszująca dała zupełnie inny wynik.

Dzięki tej czułości na zmiany hasze są idealne do porównywania, czy dwie rzeczy są dokładnie tym samym.

Kolejna ważna sprawa: funkcja haszująca działa tylko w jedną stronę. Praktycznie nie da się na podstawie hasza ustalić, jakie dane mieliśmy na początku.

Dzięki tej własności świat się nie zawali, jeśli ktoś zobaczy hasz jakichś naszych danych. Nie dojdzie do tego, że ktoś z nich wyczyta pierwotne informacje – takie jak treść pracy magisterskiej, którą wrzuciliśmy w Antyplagiat.

Uwaga

Jeśli mówimy o haszach krótkich haseł, warto jednak dmuchać na zimne i ustawiać coś ambitniejszego niż admin albo dupa.
Ktoś mający hasz naszego hasła – bez samego hasła – mógłby je ustalić metodą prób i błędów. Po kolei haszując wszelkie możliwe teksty i sprawdzając, czy wynik zgadza się z naszym haszem. Ale takie metody, nawet dla krótkich haseł, są niesamowicie niewydajne.
Jeśli mówimy o haszowaniu dłuższych tekstów, to raczej bym się nie obawiał, że ktokolwiek odzyska treść. Zaznaczam przy tym, że cyberbezpieczeństwo to nie moja działka.

Jako wisienka na torcie jeszcze to, że hasz ma stałą długość, niezależnie od rozmiaru danych wejściowych. Możemy więc łatwo ścisnąć treść całego listu, całej książki, a nawet całej biblioteki w krótki hasz. I przesłać znajomym w jednej wiadomości, na pewno się ucieszą.

Ciekawostka

Funkcje haszujące występują w wielu różnych odmianach.
Na przykład ta z Pythona daje inny wynik za każdym razem, kiedy go uruchomimy. Byłaby nieprzydatna do zadań wymagających stabilności, np. do weryfikacji haseł.
Od takich przypadków są wersje, które zawsze dają taki sam wynik. Ich przykład zawiera ten wpis.
Istnieją również bardziej egzotyczne wersje, takie jak SimHash – tworzy hasze tym bardziej podobne, im bardziej podobne były dane początkowe. Przydaje się np. w wyszukiwarkach obrazków.

Haszowanie w praktyce

We wstępie zasugerowałem kilka zastosowań haszy, które mogłyby nas zainteresować. Tutaj to nieco rozwinę.
Ich przykłady w naturze:

  • Tworzenie wydajnych programów

    Często program musi zrobić coś złożonego z każdym z wielu elementów. Ale co, jeśli sporo z nich ma identyczne właściwości? Nie ma sensu za każdym razem liczyć wszystkiego od nowa – można policzyć raz, zapamiętać wynik i przechować go na później!
    W tej sytuacji często stosuje się hasze, ponieważ sprowadzają kilka wartości do jednej liczby. Po każdym wykonaniu działań na nowej rzeczy nasz program może zapisać gdzieś parę hasz-wynik.
    A kiedy trafi się kolejna rzecz, to szybko liczymy jej hasz i patrzymy, czy mamy dla niego zapisany wynik. Jeśli nie, to obrabiamy tę rzecz od zera. Jeśli tak, to po prostu bierzemy gotowy wynik. Oszczędność czasu może być ogromna!

  • Wykrywanie, czy ktoś majstrował przy plikach.

    Popularne aplikacje i programy wydają się łakomym kąskiem dla hakerów – można do nich dodać złośliwy kod, umieścić gdzieś w internecie, a potem linkować do tej wersji w różnych miejscach. Może ktoś się nabierze!
    Hasze pozwalają się przed tym zabezpieczyć. Kiedy autor oryginalnej aplikacji wypuszcza nową wersję, może również obliczyć jej hasz i umieścić go w jakiejś centralnej bazie.
    Gdyby ktoś zmienił cokolwiek w kodzie programu i go udostępnił, to zawirusowana wersja będzie miała zupełnie inny hasz niż oryginał. Jeśli system operacyjny w jakiś sposób porównuje hasze ze wspomnianą bazą, to będzie mógł wykryć majsterkowanie, zablokować taką aplikację i ostrzec użytkownika.

  • Logowanie do stronek

    Kiedy zakładamy konto na jakiejś platformie, prawie zawsze ustalamy do niego hasło.
    Gdyby jej właściciele nie dbali o bezpieczeństwo, to mogliby przechowywać nazwę użytkownika razem z hasłem jako tekst. Wtedy, gdyby ich baza danych wyciekła, każdy mógłby skopiować nazwę i hasło. I po prostu się zalogować jako my.
    Strony bardziej dbające o bezpieczeństwo przechowują zamiast tego hasze. Przy każdym naszym logowaniu serwer przekształca hasło w hasz i sprawdza, czy ma go przy naszej nazwie użytkownika. Jeśli tak, to nas przepuszcza.
    Gdyby w takim przypadku nastąpił wyciek bazy, to nie byłby taki groźny. Mając nazwę użytkownika i hasz, włamywacz i tak nie będzie wiedział, co wpisać w polu „Hasło”!

  • Inwigilacja podczas ruchu w internecie

    No i niestety ciemna strona haszowania.
    Nawiązując do naszej serii o internetowej inwigilacji – wyobraźmy sobie, że przy każdym kontakcie ze stroną A wysyłamy jej pakiet informacji: adres IP + informacje o urządzeniu + ustawienia językowe + coś charakterystycznego.
    Nie wiemy, że strona A przesyła te informacje jakiejś organizacji gromadzącej dane – na przykład fikcyjnej SpyCorp.
    SpyCorp nie ma nas w bazie, ale oblicza hasz naszych informacji i go do niej dodaje, wraz z informacją że ktoś z takim haszem był na stronie A.
    Potem odwiedzamy stronę B, o czymś zupełnie innym. Ona również spiskuje przeciw nam i wysyła nasze informacje do SpyCorp. Nie zmieniły się od czasu wizyty na stronie A. Więc kiedy SpyCorp oblicza hasz, to odkrywa, że już go ma w bazie. Teraz wie, że odwiedziliśmy zarówno B, jak i A. Może zrobić z tą wiedzą różne rzeczy.

Bonus: jak i po co sprawdzać hasz?

Okej. Wiemy już czym jest hasz, że jest absolutnie powszechny. Pewnie jeszcze go spotkamy. Ale po co mamy umieć go sprawdzać, jeśli nie planujemy tworzyć żadnej platformy?

Możliwe że faktycznie nigdy go nie użyjecie. Dlatego oznaczyłem tę część jako bonus. Ale mam dwa mniej lub bardziej naciągane pomysły, kiedy porównywanie haszy może się przydać.

Jeśli chcecie przejść prosto do nich, to są tutaj.

Sprawdzanie przez przeglądarkę

Jeśli chcemy sprawdzić hasz jakiegoś krótszego tekstu, to możemy po prostu odwiedzić stronę wyszukiwarki DuckDuckGo.

Najpierw wpisujemy odmianę hasza, jaką chcemy sprawdzić (na przykład md5, sha1, sha256), a po niej nasz tekst. Jego hasz wyświetli się pod spodem.

Zrzut ekranu ze strony DuckDuckGo, pokazujący hasz dla tekstu 'ciemna strona'

Jeśli jednak chcemy sprawdzić hasz czegoś dłuższego, jak cały plik, możemy użyć narzędzi wbudowanych w nasz system.

Jak to zrobić na Windowsie?

Najpierw otwieracie Eksplorator (ikona Żółta ikona Eksploratora Windowsa).

Potem przechodzicie do dowolnego folderu z jakimś plikiem.
Na potrzeby pokazu stworzyłem folder hash_test, a w nim jedną rzecz – plik testowy.txt, zawierający jedynie słowa „Jakiś tekst”:

Zrzut ekranu dwóch okien Windowsa. Pierwsze pokazuje dużą ikonę pliku tekstowego w Eksploratorze. Drugie pokazuje otwarty program Notatnik, z widocznym tekstem 'Jakiś tekst'.

Klikacie w zakładkę Plik w lewym górnym rogu, a następnie na Otwórz program Windows PowerShell:

Menu Eksploratora. Druga opcja od góry, 'Otwórz program Windows PowerShell', jest otoczona czerwoną ramką.

Otworzy się konsola. Możecie w nią, za znakiem >, wpisywać różne rzeczy. A komputer będzie je robił.

Jeśli chcemy po prostu zobaczyć, jaki hasz ma plik, to najprościej tam wpisać:

Get-FileHash 'PLIK'

gdzie zamiast PLIK wpisujemy nazwę naszego pliku. Potwierdzamy, naciskając Enter. W moim przypadku wychodzi coś takiego:

Zrzut ekranu PowerShella. Na ciemnoniebieskim tle widać u góry, za strzałką, wpisany tekst 'Get-FileHash plik testowy.txt'. Tekst poniżej zawiera tekst SHA256 pod nagłówkiem 'Algorithm' oraz długi ciąg liter i cyfr pod nagłówkiem 'Hash'.

Zobaczymy hasz wraz z dodatkowymi informacjami o użytym algorytmie. Możemy go sobie zaznaczyć i skopiować przez Ctrl+C.

Domyślnie Windows używa funkcji SHA256. Ale w naturze często spotykamy też inne wersje, w tym MD5.
Żeby obliczyć hasz metodą MD5, wystarczy zmienić wpisywaną komendę na:

Get-FileHash -Algorithm MD5 'PLIK'

Żródło: Dokumentacja od Microsoft.

Uwaga

Pamiętajcie o pojedynczych cudzysłowach przed i po nazwie pliku. Gdybyście ich nie dali, a w nazwie pliku byłyby jakieś spacje, to wyskoczy błąd.

Jeśli natomiast chcemy porównać hasz pliku z innym haszem, który sami wkleimy, to używamy komendy:

(Get-FileHash 'PLIK').Hash -eq 'HASH'

Źródło: odpowiedź ze StackOverflow.

Albo, dla MD5:

(Get-FileHash -Algorithm MD5 'PLIK').Hash -eq 'HASH'

PLIK to ponownie nazwa pliku, którego hasz określamy. A HASH to jakiś inny hasz, który sami wklejamy w PowerShella.

Jeśli plik ma taki sam hasz co ten, który sami podaliśmy, to wyświetli nam napis True.

Jak to zrobić na innych systemach?

Z OS X (systemem Apple’a) nie mam doświadczenia, więc muszę polegać na wpisach innych. Według tego wpisu musimy otworzyć Terminal (odpowiednik PowerShella), a tam wpisać:

  • shasum -a 256 'PLIK', żeby policzyć metodą SHA256;
  • md5 PLIK, żeby policzyć metodą MD5.

Potem możemy porównać wynik z innym haszem „na oko”.

Brzmi łatwo i przyjemnie. Problem w tym, że podobno trudniej jest otworzyć Terminal w folderze, w którym aktualnie jesteśmy i w którym jest nasz plik. Taką opcję trzeba specjalnie włączyć.

…Albo, jeśli nam się nie chce, można (podobno) przeciągnąć plik do Terminala, żeby wstawiło nam pełną ścieżkę do niego. Wtedy nie ma znaczenia, że Terminal nie otworzył się w tym samym miejscu co plik.

Linux pod tym względem jest przyjemniejszy – a przynajmniej mój Mint, bo ogólnie dystrybucji (tzn. wersji systemu) jest mnóstwo. Wyjaśnię na jego przykładzie, używając angielskich nazw.

Wystarczy w nim przejść do określonego folderu, używając odpowiednika Eksploratora. Potem można kliknąć prawym przyciskiem i wybrać Open in Terminal.

Tam wpisujemy:

  • sha256sum PLIK, żeby policzyło SHA256;
  • md5sum PLIK, żeby policzyło MD5.

A jeśli chcemy porównać hasze, to można użyć takiego zaklęcia: md5sum -c <<< "HASH *PLIK".
(niestety trzeba pamiętać o trzech strzałkach i cudzysłowach; gdyby w nazwie pliku były spacje, to dodatkowo otaczamy ją cudzysłowami pojedynczymi; gwiazdkę można pominąć, jeśli tworzymy hasz dla pliku tekstowego).

Jeśli hasz się zgadza z tym podanym, to wyświetli nazwę pliku i OK.

Porada

W przypadku Terminala na Linuksie trzeba pamiętać o dodatkowych Shiftach! Kopiujemy tekst przez Ctrl+Shift+C, a wklejamy przez Ctrl+Shift+V.

A teraz czas na praktyczne zastosowania.

Sprawdzanie programów

Wyobraźmy sobie, że pobraliśmy jakiś program z nieznanej, dość szemranej strony. Albo, jeśli nie wyobrażamy sobie takiej sytuacji, że pobrał go jakiś rodzic/wujek.

Chcemy się upewnić, czy program jest bezpieczny. Przeszukujemy internet i znajdujemy stronę jego twórcy. Wydaje się rzetelna, ocen sporo, pozytywne.

Ale czy wersja, którą mamy z innego źródła, nie została zmodyfikowana? Czy to te same programy?

Moglibyśmy dla pewności pobrać program po raz drugi, tym razem z oficjalnej strony. To byłoby rozsądne. Ale załóżmy, że nie wchodzi w grę. Może internet szwankuje i nie chcemy zużywać danych mobilnych? Może link do pobierania na oryginalnej stronie jest nieaktywny?

Czyli zostajemy z treścią strony oryginalnej, programem ze strony niepewnej.
Jak zweryfikować, czy pobrany program nie jest zawirusowany?

Odpowiedź: patrzymy na stronę autora i wypatrujemy tej samej wersji programu, jaką pobraliśmy z dziwnej strony (np. wersję 2.12 czy coś). Jeśli znajdziemy przy niej tekst w stylu „MD5 Hash” albo „MD5 Checksum” i długi ciąg znaków, to mamy punkt zaczepienia.

Kopiujemy hasz ze strony. Następnie przechodzimy do folderu z pobranym programem i odpalamy PowerShella.
Wpisujemy (Get-FileHash -Algorithm MD5 'PLIK').Hash -eq 'HASH', dając nazwę programu zamiast PLIK i wklejając skopiowany hasz w miejsce HASH.

Jeśli wyświetli nam True, to znaczy że program ma ten sam hasz. To ta sama wersja, co z oryginalnej strony! Zatem pozory mylą, szemrana strona nie dodała żadnej niespodzianki od siebie.

…Ale pozostaje jeszcze kwestia zaufania do autora. Może tylko wydaje się miły, ale stworzył szkodliwy program i umieścił u siebie na stronie, skąd inni go skopiowali? Mógł dodać informacje o haszu, żeby robić bardziej profesjonalne wrażenie.

Pamiętajmy: hasz nic nie mówi o tym, czy źródło jest wiarygodne. Mówi tylko, czy dwie rzeczy są takie same.

Hasz byłby taki sam dla dwóch identycznych, prawilnych programów. Ale byłby też taki sam dla dwóch identycznych wirusów. To tak ku przestrodze.

Przekazywanie wiadomości „na raty”

Haszy możecie też użyć, żeby przekazać pewną informację bez ujawnienia od razu jej treści. Na przykład w celu asekuracji (czyli, mówiąc potocznie, jako dupochronu).

Powiedzmy, że macie przeczucia co do jakiejś sprawy z życia, która może rypnąć. Dowolnej. Na przykład wierzycie, że Żwirek spiskuje przeciw Muchomorkowi.

Z jednej strony nie chcecie mówić o tym wprost, na wypadek gdyby te przeczucia jednak były mylne. Jak w grze Pascala – działanie błędne bolałoby bardziej niż brak działania.
Z drugiej – jeśli przyznacie się dopiero po fakcie, że to przeczuwaliście, to nie zostaniecie wzięci na serio. Nie chcecie też słać anonimów i potem przekonywać, że były od was.

Jak to rozwiązać?
Odpowiedź: zapisujecie swoje przeczucia w jakimś pliku tekstowym. Robicie Get-FileHash 'WASZ_PLIK', żeby uzyskać jego hasz.

Plik tekstowy odkładacie w bezpieczne miejsce i pod żadnym pozorem go nie zmieniacie. Ani spacji.

Natomiast sam hasz kopiujecie i wysyłacie osobom, których dotyczy sytuacja. Zapewne zbierając szereg reakcji „WTF”, ale co tam.

Jeśli Wasze przewidywania okażą się błędne, to możecie nigdy nie wracać do sprawy tego dziwnego tekstu, który wysłaliście.
Jeśli natomiast były słuszne, to dosyłacie też oryginalny plik. I pokazujecie, że odpalenie na nim Get-FileHash daje dokładnie ten sam hasz, który wysłaliście wcześniej. A hasz jest nie do podrobienia.

Wniosek: przemyślenia opisane w pliku mieliście jeszcze przed całym zajściem. Wiedzieliście, co się kroi.

Ciekawostka

Niedawno taką metodę zastosowały trzy znane portale o cyberbezpieczeństwie: Niebezpiecznik, Zaufana Trzecia Strona oraz Informatyk Zakładowy.
Wiedzieli, że mogą pojawić się przeciw nim oskarżenia. Gdyby były, to chcieli od razu je zdementować. Ale nie chcieli uprzedzać faktów.
Dlatego 20 lutego każda z tych stron wrzuciła na swoje konto społecznościowe sam hasz oświadczenia.
A 2 marca, gdy plotki okazały się prawdziwe, dodali jego pełną treść.

Wadą rozwiązania jest to, że inni muszą mieć przynajmniej podstawowe pojęcie o haszach (a przynajmniej wiedzieć, że są nie do podrobienia). Drugą wadąZaletą to, że zapewne zostaniecie uznani za nerdów.

I z tymi nerdowskimi metodami Was zostawiam. Miłego haszowania i do zobaczenia przy kolejnych wpisach! :smile: