Kodowanie, hashowanie, szyfrowanie – to seria artykułów o tematyce bezpieczeństwa i przetwarzania danych przez komputery. Dowiecie się z nich:
– jak o bezpieczeństwo klientów dbają strony banków, a jak proste logowanie do forum
– dlaczego tak działają – jakim atakom hackerów przeciwdziałają
– jak samodzielnie zaplanować bezpieczne logowanie, przesyłanie danych, przetrzymywanie danych
Pierwsze trzy artykuły to teoria którą trzeba choć częściowo rozumieć [coś czego powinniście się nauczyć na przedmiocie BSI], aby zrozumieć czwarty artykuł prezentujący istniejące rozwiązania.
Część pierwsza z czterech:
- Kodowanie.
- Hashowanie.
- Szyfrowanie.
- Przykłady zastosowań. Analiza istniejących rozwiązań.
1. Kodowanie – jest to format zapisu informacji na komputerze. Celem kodowania jest używanie wspólnego 'języka’.
Przykładem z życia może być system dziesiętny. Jeśli zapisujący i odczytujący znają system dziesiętny to obliczenia zapisane przez jedną osobę są czytelne dla drugiej. Wspólne (i jakoś ustalone/oznaczone) kodowanie jest wymagane, aby 2 programy mogły się komunikować.
Kodowania z jakimi często się spotkasz w programowaniu:
– ANSI i UTF-8 – 2 formaty zapisu liter wykorzysywane przy przesyłaniu tekstu.
Pierwszy (ANSI) używa jednego bajta na jedną literę, pozwala to używać znaków takich jak ą,ę,ć.. , ale trzeba najpierw przekazać/ustalić jakiego alfabetu mają używać zapisujący i czytający (np. polskiego).
Drugi (UTF-8) używa jednego lub 2 bajtów na jedną literę, pierwszy z nich oznacza z jakiego alfabetu jest dany znak, a drugi już sam znak w danym alfabecie, dzięki temu na jednej stronie/w jednym programie można używać wielu języków naraz. ANSI jest wypierany na rzecz UTF-8, np. wszystkie programy w Javie używają zapisu 'string’ jako UTF-8, przez co zmienna typu 'char’ ma 2 bajty w Javie (w innych jezykach 'char’ [znak] jest równy rozmiarem 'byte’ i ma jeden bajt).
Problemem (dla programistów, nie użytkowników) z zapisem UTF-8 jest to, że litery angielskie i cyfry zapisuje się jako jeden bajt, a znaki z konkretnych języków jako 2 bajty. Dlatego zapis 'aą’ do pliku zajmuje 3 bajty i chcąc pobrać 3 znak ze stringa z pliku nie można odczytać po prostu 3-go bajtu z pliku, tylko trzeba odczytać wszystko od początku sprawdzając czy są to normalne znaki czy był znak 'zmiana alfabetu następnego znaku’. Jednak robiąc wszystko w Javie (zapis/odczyt) nie ma się czym martwić, bo Java sama ogarnie UTF-8.
Kodowania z jakimi często się spotkasz w szyfrowaniu/hashowaniu:
Mają na celu ograniczenie używanych w nich znaków do tych dostępnych na klawiaturze (jak wpisać liczbę 240 jako jeden znak (bajt) z klawiatury? ..) lub tych które można przesyłać w danym formacie danych (JSON, HTML, ..):
– zapis szesnastkowy (hexadycymalny, 'hex’), zapisanie jednego bajtu (8 bit, wartości od 0 do 255 w systemie dziesiętnym) dokonuje się za pomocą 2 znaków z zakresu 0-9 i A-F, przykład (często wynik funkcji hashujących): 32 (system dziesiętny) -> 20 (system szesnastkowy), 9 -> 9, 10 -> A, 11 -> B
– zapis ’64’ (Base64), wykorzystuje małe i duże litery angielskie, cyfry 0-9 oraz kilka znaków specjalnych (tak, aby były w sumie 64 różne znaki), często wykorzystywany do przesyłania danych zaszyfrowanych na strony WWW (ze względu na to, że znaki takie jak < i > są 'specjalne’ w HTMLu) oraz w popularnym formacie do przesyłania danych 'JSON’, gdzie też jest ograniczenie co do dopuszczalnych znaków.
Czasem jest też wykorzystywany do zapisywania danych/kluczy w bazie danych kiedy chce się je przechowywać w sposób czytelny w polu string, a nie jako ciąg bajtów (np. w kolumnie typu 'blob’ lub inne do przechowywania danych binarnych).
Podsumowując, kodowanie jest stosowane, aby różne programy mogły się ze sobą komunikować używając takich samych znaków – aby komunikacja była możliwa.
Możliwe zastosowania:
– zapis kluczy/danych do przesłania używając formatu który nie pozwala na przesyłanie 'binarne’ (kiedy bajt może przyjąć dowolną wartość od 0 do 255 – dowolny znak)
– zapis klucza/hasha tak, aby użytkownik mógł go wpisać z klawiatury (np. klucz logowania do sieci WiFi w routerach domowych)
Zastosowanie 'dziwne’:
Zmiana kodowania na nietypowe. Przykład: przesyłanie zaszyfrowanych danych w systemie 62-owym zamiast popularnego 64-owego. Wystarczy napisać funkcje która zapisuje dane używając 62 różne znaki zamiast 64 i dorzucić losowo 2 pozostałe znaki z 64-owego kodowania, a przy odczycie ignorować te 2 znaki. Wtedy osoba (hacker) która 'podsłuchuje’ wasze połączenie (ale nie ma dostępu do kodu programu, żeby sprawdzić kodowanie) próbując się włamać zmarnuje 5-15 minut zanim ogarnie które znaki są nie istotne i jakie kodowanie jest używane lub podda się i poszuka innego celu który łatwiej złamać. Takie rozwiązanie jest mało skutecznie w przypadku ataku konkretnie na wasz program, ale w przypadku kogoś kto chce 'coś’ zhackować może go zniechęcić.