Base64 і Base64URL працюють за одним принципом: перетворюють байти на послідовність символів із алфавіту розміром 64. Для більшості вхідних даних результати навіть виглядають однаково. Різниця стосується лише кількох символів і правила доповнення, але саме вона вирішує, чи переживе значення передавання всередині URL без додаткових перетворень.

Чому звичайний Base64 незручний в адресах

Стандартний Base64 використовує символи +, / і =. У текстовому файлі вони не створюють проблем, але в URL уже мають власні ролі. Скісна риска розділяє частини шляху, знак рівності відділяє назву параметра від значення, а плюс у form-urlencoded запитах часто означає пробіл.

Якщо вставити стандартний Base64 у query string без додаткового кодування, парсер може змінити значення ще до того, як його отримає бізнес-логіка. Можна застосувати percent-encoding, але тоді рядок стає довшим, а кожна сторона повинна правильно виконати ще один етап перетворення.

Що змінює Base64URL

Base64URL замінює плюс на дефіс, а скісну риску — на підкреслення. Обидва символи значно простіше використовувати в URL, назвах файлів і cookie. Завершальні знаки рівності зазвичай прибирають, оскільки їх можна відновити за довжиною рядка.

Усі літери й цифри залишаються незмінними. Через це короткий тест може випадково показати однаковий результат для обох форматів. Помилка проявиться пізніше, коли інші дані породять плюс, скісну риску або потребуватимуть доповнення.

Найвідоміший приклад — JWT

JSON Web Token складається з трьох частин, розділених крапками: заголовка, payload і підпису. Кожна частина використовує Base64URL, бо токени передаються в HTTP-заголовках, cookie та іноді в посиланнях. Звичайний Base64 може випадково спрацювати для конкретного payload, але він не відповідає формату JWT.

Base64URL не робить вміст токена приватним. Заголовок і payload може прочитати будь-хто, хто має токен. Цілісність забезпечує підпис, а конфіденційність потребує окремого шифрування. URL-безпечне кодування лише робить сегменти зручними для транспортування.

Доповнення має бути частиною контракту

Стандартний Base64 зазвичай доповнює результат до довжини, кратної чотирьом. Для Base64URL протоколи часто дозволяють або вимагають рядок без =. Гнучкий декодер може обчислити потрібну кількість знаків, відновити їх і лише потім виконати декодування.

Проблеми виникають, коли одна сторона приймає обидва варіанти, а інша — лише один. Для підписаних значень це особливо важливо: два текстові представлення тих самих байтів залишаються різними рядками, тому підпис перевіряють над точно визначеною формою.

Коли використовувати кожен формат

Стандартний Base64 потрібен там, де його прямо вимагає формат: у MIME-вкладеннях, PEM-блоках і багатьох наявних API. Не варто самостійно змінювати його на URL-безпечний варіант лише тому, що запит передається через HTTP. Важливим є контракт конкретного поля.

Base64URL варто застосовувати, коли закодоване значення має бути безпосередньо частиною адреси, назви файлу, cookie або формату, який явно визначає URL-безпечний алфавіт. Назви функцій у коді повинні показувати варіант: encodeBase64Url значно зрозуміліше за універсальне encode.

Як уникнути проблем сумісності

Документуйте алфавіт і правило доповнення для кожного поля. Додайте тести зі значеннями, які породжують відмінні символи, а не лише літери й цифри. Перевіряйте malformed input і не видаляйте мовчки незнайомі символи: це може приховати пошкодження або неправильний формат.

Під час діагностики порівнюйте значення на кожній межі: до побудови URL, у сирому HTTP-запиті та після парсингу фреймворком. Плюс або percent-encoded послідовність можуть змінитися ще до виклику декодера.

Міграція між варіантами потребує обережності

Якщо наявний API переходить зі standard Base64 на Base64URL, недостатньо просто змінити два символи у новому кодері. Старі клієнти можуть надсилати доповнення, збережені значення можуть мати стандартний алфавіт, а підписи можуть залежати від точного текстового представлення.

Безпечна міграція зазвичай має період сумісного читання, але лише один канонічний формат для нових записів. Метрики й журнали помилок допомагають побачити, коли старий варіант більше не використовується.

Не визначайте варіант за зовнішнім виглядом

Рядок, який містить лише літери та цифри, може бути коректним одночасно для обох алфавітів. Тому автоматичне визначення варіанта працює не завжди. Контекст поля або протокол повинен повідомляти, який формат застосовано.

Якщо система змушена приймати обидва варіанти, вона має декодувати їх контрольовано й повертати один узгоджений формат. Це зменшує кількість еквівалентних представлень і спрощує кешування, підписування та порівняння.

Підписані значення потребують канонічної форми

Для звичайного декодування рядки з доповненням і без нього можуть означати ті самі байти. Для цифрового підпису вони різні, бо підпис обчислюється над конкретними символами. Якщо одна сторона нормалізує значення перед перевіркою, а інша підписує сирий рядок, інтеграція буде нестабільною.

Протокол повинен чітко визначати, що саме підписується: оригінальний Base64URL-рядок, декодовані байти чи канонічно сформоване повідомлення. Реалізації мають повторювати це правило без самостійного «покращення» формату.

Тести повинні охоплювати проблемні символи

Приклади на кшталт слова Hello зручні для документації, але часто не містять символів, які відрізняють два варіанти. Додайте відомі набори байтів, результат яких містить плюс, скісну риску, дефіс, підкреслення та різну кількість доповнення.

Окремо перевіряйте порожнє значення, один і два байти, неправильну довжину та сторонні символи. Такі тести фіксують реальну політику декодера й не дозволяють бібліотечному оновленню непомітно змінити сумісність.

Мала відмінність із конкретною метою

Base64URL не є «кращою» чи безпечнішою версією Base64. Це той самий спосіб представлення байтів, адаптований до середовища, де кілька стандартних символів мають спеціальне значення. Обидва формати надійні, якщо сторони точно погодили варіант.

Найкраща практика — ставитися до них як до двох окремо названих кодувань. Тоді вибір стає очевидним, а випадкові помилки не ховаються за майже однаковими рядками.