Как кодировать и декодировать Base45
- Введите или вставьте текст в поле Ввод · Текст. Строка Base45 появится в поле Результат · Base45 (RFC 9285).
- Для двоичных данных, например сжатых байтов, сначала выберите в меню Из вариант Hex или Base64.
- Чтобы декодировать, нажмите Base45 (RFC 9285) → Текст в переключателе направления и вставьте строку. Если результат двоичный (у медицинских сертификатов он именно такой), выберите Hex или Base64 в меню В.
- Скопировать результат сохраняет пробелы. Сохранить байты скачивает декодированные байты файлом.
Как работает Base45
RFC 9285 берёт ввод по два байта. Каждая пара образует число n от 0 до 65535, которое записывается тремя цифрами по основанию 45: c, d, e, где n = c + d × 45 + e × 45², младшая цифра идёт первой. Последний одиночный байт превращается в две цифры. Алфавитом служит алфавитно-цифровой набор QR-кода в исходном порядке:
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:
Примеры из RFC, все воспроизводятся этим инструментом:
| Ввод | Base45 |
|---|---|
AB | BB8 |
Hello!! | %69 VD92EX0 |
base-45 | UJCLQE7W581 |
ietf! | QED8WEX0 |
При декодировании проверяются две вещи, которые нестрогий декодер мог бы пропустить: длина 3n + 1 не может получиться ни из какого ввода, а группа больше 65535 (например, GGW или ZZZ) выходит за допустимый диапазон. Оба случая дают ошибку.
Почему Base45 подходит для QR-кодов
На бумаге Base45 выглядит расточительным: 3 символа на 2 байта дают рост на 50%, больше, чем 33% у Base64. Выигрыш объясняется тем, как QR-коды хранят текст. В алфавитно-цифровом режиме QR-код упаковывает два из этих 45 символов в 11 бит. Значит, три символа Base45 занимают 16,5 бита на 16 бит данных, то есть накладные расходы около 3%.
Base64 не может использовать алфавитно-цифровой режим, потому что ему нужны строчные буквы. Ему остаётся байтовый режим по 8 бит на символ, а это рост на 33% внутри QR-кода. Для тех же данных QR-код с Base45 получается меньше или вмещает больше.
Декодирование EU Digital COVID Certificate (HC1:)
QR-код EU Digital COVID Certificate хранит строку, которая начинается с HC1:. Данные собраны в несколько слоёв, и эта страница снимает один из них:
- Уберите префикс
HC1:.H,C,1и:входят в алфавит Base45, поэтому оставленный префикс декодируется как данные и ломает всё, что идёт после него. - Декодируйте Base45. Вставьте остаток сюда и выберите в меню В вариант Base64.
- Распакуйте результат. Это данные zlib, которые начинаются с байта
78(eJилиeNв Base64). Вставьте Base64 в декодер gzip и zlib. - Разберите CBOR. Распакованные байты содержат структуру COSE_Sign1 в CBOR: заголовок, полезная нагрузка с полями сертификата и подпись. Для неё нужен декодер CBOR, которого на этом сайте нет.
Декодирование показывает содержимое, но не проверяет подпись. Чтобы убедиться в подлинности сертификата, нужны открытый ключ страны-эмитента и верификатор COSE.
Base45 в Python
В стандартной библиотеке Python модуля Base45 нет. Кодировщик напрямую следует RFC:
ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"
def b45encode(data: bytes) -> str:
out = []
for i in range(0, len(data) - 1, 2):
n = data[i] * 256 + data[i + 1]
c, n = n % 45, n // 45
d, e = n % 45, n // 45
out += ALPHABET[c], ALPHABET[d], ALPHABET[e]
if len(data) % 2:
c, d = data[-1] % 45, data[-1] // 45
out += ALPHABET[c], ALPHABET[d]
return "".join(out)
b45encode(b"ietf!") # 'QED8WEX0'
Пакет base45 на PyPI умеет оба направления. Работа с байтами в Python подробнее описана на странице про Python.
Вопросы и ответы
Почему в результате Base45 есть пробелы?
Пробел входит в число 45 символов алфавитно-цифрового набора QR, поэтому в Base45 это обычная цифра со значением 36. Hello!! кодируется в %69 VD92EX0. Сохраняйте пробелы при копировании и не давайте форме или оболочке их обрезать.
Можно ли здесь декодировать EU Digital COVID Certificate?
Частично. Эта страница выполняет шаг Base45. Дальше идут данные CBOR, сжатые zlib, внутри подписанной структуры COSE, и для них нужны распаковка и декодер CBOR. Шаги перечислены на этой странице.
Можно ли вставлять Base45 в URL?
Нет. Пробел, %, + и / входят в алфавит, и все они имеют особый смысл в URL. Закодируйте строку процентным кодированием или используйте для URL Base64URL.
Почему моя строка Base45 отвергается?
Корректный Base45 имеет длину 3n или 3n + 2 символа, и каждая группа из 3 символов должна быть не больше 65535. Длина 3n + 1 или группа вроде GGW дают ошибку. Часто виноват оставшийся префикс HC1:.