Base64
7 narzędzi
Czym jest kodowanie?
Kodowanie to proces przekształcania danych z jednej reprezentacji na inną. W tworzeniu stron internetowych kodowanie służy do bezpiecznego przesyłania danych przez kanały zaprojektowane dla ograniczonego zestawu znaków — na przykład do wysyłania danych binarnych przez protokół tekstowy lub umieszczania znaków specjalnych w URL.
Kodowanie znaków określa, jak znaki tekstowe są odwzorowywane na bajty. Kodowanie Base64 przekształca dane binarne na tekst ASCII. Kodowanie URL sprawia, że dowolny tekst jest bezpieczny do użycia w adresach URL. Zrozumienie tych trzech warstw kodowania zapobiega subtelnym błędom i lukom bezpieczeństwa.
Historia kodowania znaków
Kodowanie znaków to odwzorowanie między znakami (literami, symbolami) a ich binarnymi reprezentacjami. Ewolucja od ASCII do Unicode odzwierciedla globalizację internetu:
7-bitowy amerykański kod standardowy. 128 znaków: angielskie litery, cyfry, znaki interpunkcyjne i kody sterujące. Zdefiniował podstawowe kodowanie, na którym opierają się wszystkie inne.
Rozszerzony ASCII dla języków Europy Zachodniej. Dodał 128 znaków (litery z akcentami, symbole). Nieodpowiedni dla pisma nielatyńskiego.
Uniwersalny zestaw znaków obejmujący wszystkie systemy pisma na świecie. Definiuje punkty kodowe dla ponad 149 000 znaków w 161 skryptach. Nie definiuje kodowania — to zadanie UTF-8/16/32.
Kodowanie o zmiennej szerokości używające 1–4 bajtów na znak. Kompatybilne z ASCII (pierwsze 128 punktów kodowych to pojedyncze bajty). Dominujące kodowanie w sieci — ponad 98% stron internetowych.
Kodowanie o zmiennej szerokości używające 2 lub 4 bajtów na znak. Stosowane wewnętrznie przez Windows, Java i ciągi znaków JavaScript. Niekompatybilne z ASCII.
Kodowanie o stałej szerokości: zawsze 4 bajty na znak. Proste, ale marnuje miejsce. Stosowane w niektórych wewnętrznych mechanizmach baz danych. Rzadko spotykane w sieci.
Dlaczego wygrało UTF-8
UTF-8 stało się dominujące, ponieważ jest wstecznie kompatybilne z ASCII (pierwsze 128 znaków koduje się identycznie), jest samosynchronizujące (granice znaków można znaleźć przez skanowanie) i efektywnie wykorzystuje miejsce dla tekstu łacińskiego. Każdy dokument ASCII jest prawidłowym dokumentem UTF-8. Dzięki temu migracja była bezproblemowa.
Kodowanie Base64
Base64 przekształca dane binarne na reprezentację tekstową, używając jedynie 64 drukowalnych znaków ASCII: A–Z, a–z, 0–9, + i /. Jest to konieczne, gdy dane binarne muszą przechodzić przez kanały obsługujące wyłącznie tekst — załączniki e-mail, data URI, tokeny JWT i HTTP Basic Auth — wszystkie korzystają z Base64.
Jak to działa
Base64 grupuje bajty wejściowe w 3-bajtowe (24-bitowe) bloki i koduje każdy blok jako 4 znaki Base64 (po 6 bitów każdy). Jeśli dane wejściowe nie są wielokrotnością 3 bajtów, dodawane są znaki dopełnienia =, aby uzupełnić ostatnią grupę:
| Wejście | Bajty hex | Base64 |
|---|---|---|
| "Man" | 77 61 6E | TWFu |
| "Ma" | 4D 61 | TWE= |
| "M" | 4D | TQ== |
Znaki dopełnienia = na końcu wskazują, ile bajtów brakowało do uzupełnienia ostatniej 3-bajtowej grupy. Jeden = oznacza, że potrzebny był jeden bajt dopełnienia; == oznacza, że potrzebne były dwa bajty. Standardowy Base64 zawsze generuje wynik, którego długość jest wielokrotnością 4.
Kodowanie URL
Adresy URL mogą zawierać tylko ograniczony zestaw bezpiecznych znaków ASCII. Każdy znak spoza tego zestawu — w tym spacje, znaki interpunkcyjne, znaki spoza ASCII oraz specjalne znaki URL takie jak &, = i # — musi zostać zakodowany procentowo (URL-encoded) przed umieszczeniem w adresie URL.
Kodowanie procentowe zastępuje każdy niebezpieczny bajt znakiem % po którym następują dwie cyfry szesnastkowe reprezentujące wartość tego bajtu. Spacja staje się %20, ampersand staje się %26 itd.
Często kodowane znaki
| Znak | Zakodowany | Uwagi |
|---|---|---|
| Space | %20 | Najczęstszy; używany w przesyłaniu formularzy jako + w application/x-www-form-urlencoded |
| & | %26 | Separator ciągu zapytania; musi być zakodowany gdy używany jako wartość dosłowna |
| = | %3D | Separator klucz-wartość w ciągach zapytania; koduj gdy używany jako dane |
| + | %2B | Interpretowany jako spacja w application/x-www-form-urlencoded; koduj, aby zachować dosłowny + |
| # | %23 | Identyfikator fragmentu; koduj gdy używany jako dane dosłowne w ścieżce lub zapytaniu |
| / | %2F | Separator segmentów ścieżki; koduj gdy używany jako dane dosłowne, nie jako ogranicznik ścieżki |
| : | %3A | Separator schematu; koduj w kontekstach ścieżki i zapytania |
| @ | %40 | Używany w mailto: i uwierzytelnianiu; koduj gdy używany jako dane dosłowne |
encodeURI vs encodeURIComponent
JavaScript udostępnia dwie funkcje kodowania o różnym zakresie. encodeURI koduje kompletny URL — pozostawia znaki mające znaczenie w URL-ach (:, /, ?, #, @) niezakodowane. encodeURIComponent koduje komponent URL (wartość pojedynczego parametru zapytania lub segment ścieżki) — koduje wszystkie znaki oprócz A-Z, a-z, 0-9, -, _, ., ~. Zawsze używaj encodeURIComponent dla pojedynczych wartości i encodeURI dla kompletnych URL-ów.
Gdzie kodowanie pojawia się w tworzeniu stron internetowych
Nagłówek Authorization: Basic koduje dane uwierzytelniające jako Base64(nazwa_użytkownika:hasło). Jest to kodowanie dla wygody transportu, NIE bezpieczeństwa — Base64 jest trywialnie odwracalne. Zawsze używaj HTTPS z Basic Auth.
Data URI osadzają zawartość pliku bezpośrednio w HTML lub CSS: data:image/png;base64,.... Kodowanie Base64 obrazów i czcionek inline eliminuje żądania HTTP kosztem zwiększonego rozmiaru dokumentu (narzut ~33%).
Poczta elektroniczna została zaprojektowana dla 7-bitowego ASCII. Binarne załączniki (obrazy, pliki PDF) są kodowane Base64 przez MIME przed transmisją. Klient poczty dekoduje je automatycznie podczas wyświetlania wiadomości.
Tokeny JWT używają kodowania Base64url (wariant zastępujący + przez - i / przez _, bez dopełnienia) dla wszystkich trzech części (nagłówek, ładunek, podpis). Dzięki temu tokeny są bezpieczne w URL bez dodatkowego kodowania procentowego.
Wszelkie dane dostarczone przez użytkownika w ciągach zapytania URL muszą być zakodowane procentowo. Nieodkodowanie & lub = w wartości po cichu uszkodzi parsowanie ciągu zapytania. Zawsze używaj encodeURIComponent dla pojedynczych wartości.
Nazwy domen spoza ASCII (np. münchen.de) są kodowane przy użyciu Punycode (prefiks xn--) dla kompatybilności z systemem DNS. Przeglądarka wyświetla postać Unicode, ale wysyła postać Punycode do resolverów DNS.
Często zadawane pytania
Nie. Base64 to kodowanie, nie szyfrowanie. Jest to odwracalna transformacja bez tajnego klucza. Każdy, kto zobaczy ciąg Base64, może go natychmiast zdekodować. Nigdy nie używaj Base64 jako środka bezpieczeństwa.
Base64 przetwarza dane wejściowe w grupach po 3 bajty. Jeśli dane wejściowe nie są wielokrotnością 3 bajtów, dodawane jest dopełnienie =, aby uzupełnić ostatnią grupę. Jeden = oznacza jeden bajt dopełnienia; == oznacza dwa. Niektóre implementacje pomijają dopełnienie (Base64url dla JWT).
Base64url to wariant Base64 bezpieczny dla URL, który zastępuje + przez - i / przez _, i zazwyczaj pomija dopełnienie =. Dzięki temu można go bezpiecznie używać w URL-ach i nagłówkach HTTP bez kodowania procentowego. JWT używa Base64url dla wszystkich trzech części.
Używaj encodeURIComponent dla pojedynczych wartości (wartości parametrów zapytania, wartości segmentów ścieżki). Używaj encodeURI dla kompletnego ciągu URL, gdy chcesz zachować znaki struktury URL (/, :, ?, #). W razie wątpliwości używaj encodeURIComponent.
UTF-8 jest kompatybilne z ASCII i efektywnie wykorzystuje miejsce dla tekstu łacińskiego (większość URL-ów, tagów HTML i kodu to ASCII). UTF-16 marnuje miejsce dla treści ASCII i nie jest wstecznie kompatybilne. HTTP i HTML domyślnie używają UTF-8.
Kodowanie procentowe (kodowanie URL) reprezentuje znaki jako % po którym następuje ich dwucyfrowa szesnastkowa wartość bajtu. Na przykład spacja to %20 (dziesiętnie 32, szesnastkowo 20). Wielobajtowe znaki UTF-8 kodują każdy bajt oddzielnie: é to %C3%A9.
Base64 zwiększa rozmiar danych o około 33% i dodaje narzut procesora na kodowanie/dekodowanie. W systemach o wysokiej przepustowości preferuj protokoły binarne. Kodowanie URL dodaje minimalny narzut, ale może znacznie wydłużyć URL-e przy wielu znakach specjalnych.
Punycode to kodowanie służące do reprezentowania znaków Unicode w kompatybilnym z ASCII systemie DNS. Umiędzynarodowione nazwy domen, takie jak münchen.de, są kodowane jako xn--mnchen-3ya.de w zapytaniach DNS. Przeglądarki wyświetlają postać Unicode, ale wewnętrznie używają Punycode.