Base64
7 інструментів
Що таке кодування?
Кодування — це процес перетворення даних з одного представлення в інше. У веброзробці кодування використовується для безпечної передачі даних через канали, що призначені для обмеженого набору символів — наприклад, пересилання двійкових даних текстовим протоколом або включення спеціальних символів у URL.
Кодування символів визначає, як текстові символи відображаються в байти. Base64 перетворює двійкові дані на ASCII-текст. URL-кодування робить довільний текст придатним для використання в URL. Розуміння цих трьох рівнів кодування запобігає непомітним помилкам і вразливостям безпеки.
Історія кодування символів
Кодування символів — це відповідність між символами (літерами, знаками) та їх двійковими представленнями. Еволюція від ASCII до Unicode відображає глобалізацію вебу:
7-бітний американський стандартний код. 128 символів: англійські літери, цифри, знаки пунктуації та керуючі коди. Визначив базове кодування, на якому ґрунтуються всі інші.
Розширений ASCII для західноєвропейських мов. Додано 128 символів (літери з діакритичними знаками, символи). Не підходить для нелатинських письмен.
Універсальний набір символів, що охоплює всі системи письма у світі. Визначає кодові точки для понад 149 000 символів у 161 системі письма. Не визначає кодування — це завдання UTF-8/16/32.
Кодування Unicode зі змінною шириною: від 1 до 4 байт на символ. Сумісне з ASCII (перші 128 кодових точок — однобайтові). Домінуюче кодування у вебі — понад 98% вебсайтів.
Кодування зі змінною шириною: 2 або 4 байт на символ. Використовується внутрішньо у Windows, Java та JavaScript-рядках. Не сумісне з ASCII.
Кодування з фіксованою шириною: завжди 4 байт на символ. Просте, але витрачає простір. Використовується у деяких внутрішніх базах даних. Рідко зустрічається у вебі.
Чому переміг UTF-8
UTF-8 став домінуючим, оскільки він зворотно сумісний з ASCII (перші 128 символів кодуються ідентично), самосинхронізується (межі символів можна знайти скануванням) та є ефективним за розміром для латинського тексту. Будь-який ASCII-документ є валідним UTF-8-документом. Це зробило міграцію безперервною.
Кодування Base64
Base64 перетворює двійкові дані на текстове представлення, використовуючи лише 64 друковані ASCII-символи: A–Z, a–z, 0–9, + та /. Це необхідно, коли двійкові дані мають проходити через канали, що підтримують лише текст — вкладення електронної пошти, data URI, JWT-токени та HTTP Basic Auth — все це використовує Base64.
Як це працює
Base64 групує вхідні байти в блоки по 3 байт (24 біт) і кодує кожен блок як 4 символи Base64 (по 6 біт кожен). Якщо розмір вхідних даних не кратний 3 байтам, додаються символи доповнення =, щоб завершити останню групу:
| Вхідні дані | Шістнадцяткові байти | Base64 |
|---|---|---|
| "Man" | 77 61 6E | TWFu |
| "Ma" | 4D 61 | TWE= |
| "M" | 4D | TQ== |
Символи доповнення = наприкінці вказують, скільки байт бракувало для завершення останньої 3-байтової групи. Один = означає, що потрібен один байт доповнення; == означає два байти. Стандартний Base64 завжди виводить рядок, довжина якого кратна 4.
Кодування URL
URL може містити лише обмежений набір безпечних ASCII-символів. Будь-який символ поза цим набором — включаючи пробіли, знаки пунктуації, не-ASCII-символи та спеціальні символи URL на зразок &, = та # — має бути закодований у відсотковій нотації (URL-кодування) перед розміщенням у URL.
Відсоткове кодування замінює кожен небезпечний байт символом % і двома шістнадцятковими цифрами, що представляють значення цього байту. Пробіл стає %20, амперсанд — %26 тощо.
Символи, що часто кодуються
| Символ | Закодовано | Примітки |
|---|---|---|
| Space | %20 | Найпоширеніший; у відправленнях форм замінюється на + у application/x-www-form-urlencoded |
| & | %26 | Роздільник рядка запиту; необхідно кодувати при використанні як буквального значення |
| = | %3D | Роздільник ключ-значення у рядках запиту; кодуйте при використанні як даних |
| + | %2B | Інтерпретується як пробіл у application/x-www-form-urlencoded; кодуйте для збереження буквального + |
| # | %23 | Ідентифікатор фрагмента; кодуйте при використанні як буквальних даних у шляху або запиті |
| / | %2F | Роздільник сегментів шляху; кодуйте при використанні як буквальних даних, а не як роздільника шляху |
| : | %3A | Роздільник схеми; кодуйте у контекстах шляху та запиту |
| @ | %40 | Використовується у mailto: та аутентифікації; кодуйте при використанні як буквальних даних |
encodeURI vs encodeURIComponent
JavaScript надає дві функції кодування з різною областю дії. encodeURI кодує повний URL — залишає символи, що мають значення в URL (:, /, ?, #, @), некодованими. encodeURIComponent кодує компонент URL (значення окремого параметра запиту або сегмент шляху) — кодує всі символи, крім A–Z, a–z, 0–9, -, _, ., ~. Завжди використовуйте encodeURIComponent для окремих значень і encodeURI для повних URL.
Де кодування застосовується у веброзробці
Заголовок Authorization: Basic кодує облікові дані як Base64(username:password). Це кодування для зручності передачі, але НЕ безпека — Base64 тривіально оборотний. Завжди використовуйте HTTPS разом з Basic Auth.
Data URI вбудовують вміст файлу безпосередньо в HTML або CSS: data:image/png;base64,.... Вбудовування зображень і шрифтів у Base64 усуває HTTP-запити ціною збільшення розміру документа (~33% накладних витрат).
Електронна пошта була розроблена для 7-бітного ASCII. Двійкові вкладення (зображення, PDF) кодуються у Base64 за допомогою MIME перед передачею. Поштовий клієнт розкодовує їх прозоро під час відображення листа.
JWT-токени використовують кодування Base64url (варіант, що замінює + на - і / на _, без доповнення) для всіх трьох частин (заголовок, корисне навантаження, підпис). Це робить токени безпечними для URL без додаткового відсоткового кодування.
Будь-які дані, надані користувачем у рядках запиту URL, мають бути закодовані у відсотковій нотації. Не кодуючи & або = у значенні, ви непомітно пошкодите синтаксичний аналіз рядка запиту. Завжди використовуйте encodeURIComponent для окремих значень.
Доменні імена, що містять не-ASCII-символи (наприклад, münchen.de), кодуються за допомогою Punycode (префікс xn--) для сумісності з системою DNS. Браузер відображає форму Unicode, але надсилає форму Punycode до DNS-резолверів.
Часті запитання
Ні. Base64 — це кодування, а не шифрування. Це оборотне перетворення без секретного ключа. Будь-хто, хто бачить рядок Base64, може миттєво його декодувати. Ніколи не використовуйте Base64 як захід безпеки.
Base64 обробляє вхідні дані групами по 3 байт. Якщо розмір вхідних даних не кратний 3 байтам, додається доповнення =, щоб завершити останню групу. Один = означає один байт доповнення; == означає два. Деякі реалізації опускають доповнення (Base64url для JWT).
Base64url — це безпечний для URL варіант Base64, що замінює + на - і / на _, та зазвичай опускає доповнення =. Це робить його безпечним для використання в URL і HTTP-заголовках без відсоткового кодування. JWT використовують Base64url для всіх трьох частин.
Використовуйте encodeURIComponent для окремих значень (значення параметрів запиту, значення сегментів шляху). Використовуйте encodeURI для повного рядка URL, коли потрібно зберегти структурні символи URL (/, :, ?, #). Якщо сумніваєтеся — використовуйте encodeURIComponent.
UTF-8 сумісний з ASCII та ефективний за розміром для латинського тексту (більшість URL, HTML-тегів і коду — ASCII). UTF-16 витрачає простір для ASCII-вмісту і не є зворотно сумісним. HTTP і HTML за замовчуванням використовують UTF-8.
Відсоткове кодування (URL-кодування) представляє символи як % і дві шістнадцяткові цифри значення байту. Наприклад, пробіл — це %20 (десяткове 32, шістнадцяткове 20). Багатобайтові UTF-8-символи кодують кожен байт окремо: é — це %C3%A9.
Base64 збільшує розмір даних приблизно на 33% і додає навантаження на CPU при кодуванні/декодуванні. Для систем із великою пропускною здатністю надавайте перевагу двійковим протоколам. URL-кодування додає мінімальне навантаження, але може значно подовжити URL при великій кількості спеціальних символів.
Punycode — це кодування для представлення Unicode-символів у ASCII-сумісній системі DNS. Інтернаціоналізовані доменні імена, як-от münchen.de, кодуються як xn--mnchen-3ya.de у DNS-запитах. Браузери відображають форму Unicode, але внутрішньо використовують Punycode.