КИБЕРБЕЗОПАСНОСТЬ

Ink & Switch показала bijou64 — varint без двусмысленных байтов

Ink & Switch представила bijou64 — varint-кодирование, которое декодируется в 2-10 раз быстрее LEB128 и убирает класс ошибок каноничности.

✍️ Редакция iTech News | 24.07.2026 | ⏱ 5 мин | Источник: InfoQ
🔑

Исследовательская лаборатория Ink & Switch представила bijou64 — varint-кодирование, в котором у каждого числа есть ровно одно корректное байтовое представление. Для разработчиков это не очередная игра в микрооптимизации: формат обещает убрать целый класс ошибок каноничности, на которых в разное время обжигались криптографические библиотеки, системы подписи и даже экосистема Bitcoin.

О новинке сообщает InfoQ: bijou64 разработал Brooklyn Zelenka для протокола синхронизации Subduction, где нужно было исключить двусмысленность представления данных без навешивания дополнительных проверок на декодер. Идея простая, но болезненно практичная: если формат в принципе не допускает альтернативных кодировок одного и того же числа, то программист уже не сможет «забыть» проверить каноничность входа, потому что проверять будет нечего.

Проблема, которую бьет bijou64, хорошо знакома всем, кто работал с бинарными протоколами и сериализацией. В классическом LEB128 число режется на 7-битные куски, а каждый байт получает бит продолжения. Это удобно и компактно, но открывает неприятную лазейку: одно и то же значение можно закодировать несколькими способами. Ноль, например, представим как одним байтом, так и более длинной последовательностью. Спецификация обычно требует от декодера отбрасывать неканоничные варианты, но на практике именно здесь и появляются баги: проверку опускают, выносят в отдельную ветку, оптимизируют слишком агрессивно или просто забывают добавить в один из портов. В системах с цифровыми подписями, content addressing и консенсусом такая «мелочь» быстро превращается в поверхность атаки.

В материале InfoQ этот класс проблем связывают с историческими инцидентами вокруг PKCS#1 v1.5, GnuTLS и изменяемости транзакций в Bitcoin. Общая механика там одна и та же: разные байтовые формы могут описывать одно и то же значение, а значит, где-то между парсером, валидатором и логикой подписи обязательно появится шанс на рассинхрон. Bijou64 пытается закрыть вопрос на уровне конструкции формата. Для значений от 0 до 247 первый байт сам и есть число, без дополнительной служебной нагрузки. Байты от 248 до 255 используются как теги длины: они показывают, сколько байтов полезной нагрузки идет дальше. При этом у каждого диапазона есть фиксированное смещение, из-за чего маленькое число нельзя «дополнить нулями» и легально протащить в более длинном представлении. Иначе говоря, запасных входов для одного значения здесь просто не оставили.

Вторая часть истории не менее интересна: bijou64 продают не только как более строгий, но и как более быстрый формат. По данным Ink & Switch, на x86 и ARM малые числа декодируются примерно вдвое быстрее, чем в LEB128, а на крупных значениях разница доходит до 8-10 раз. Причина в том, что декодеру не нужно продираться через каскад битовых масок и проверок битов продолжения. Полезная нагрузка хранится как непрерывное big-endian-значение, поэтому компилятор может свести разбор к одному чтению и перестановке байтов. Для разработчика инфраструктуры это звучит почти как редкая удача: иногда безопасность действительно удается улучшить не ценой просадки по производительности, а вместе с ней.

Правда, техническое сообщество встретило анонс без лишнего восторга, и это скорее плюс. В обсуждении на Hacker News часть комментаторов заметила, что сравнение со «скалярными» декодерами LEB128 не закрывает вопрос о производительности в целом. Один из участников напомнил о бенчмарках формата BONJSON и утверждал, что при использовании SIMD-инструкций ULEB128 или схемы с sentinel-значениями могут снова выйти вперед за счет лучшей параллелизации. Проще говоря, bijou64 может быть быстрее в честном одноядерном лобовом тесте, но на высокопроизводительных парсерах будущего игра может идти уже по другим правилам.

Была и вторая линия критики — по безопасности. Комментатор dzaima отметил, что bijou64 не избавляет код от проверок полностью, а лишь сдвигает опасную границу. Самый длинный случай все равно требует контроля диапазона: если обработать вариант с первым байтом 255 без аккуратной проверки и позволить 64-битное переполнение, получится баг уже нового типа. Аргумент неприятный, но полезный. Формат действительно убирает классическую проблему неканоничных представлений, однако не освобождает разработчика от базовой дисциплины парсинга. Это, пожалуй, главное практическое замечание для команд, которые любят трактовать «безопаснее по конструкции» как «можно не ревьюить код декодера».

Есть и еще один нюанс, важный не только для специалистов по security, но и для тех, кто строит toolchain. Неканоничные представления иногда нужны не по ошибке, а специально. В заметке приводят пример WebAssembly и DWARF, где линкеры используют varint с запасом по длине, чтобы позже патчить ссылки на месте. Для таких сценариев жесткая однозначность bijou64 уже не выглядит безусловным плюсом: удобство безопасного декодирования обменивается на потерю гибкости при низкоуровневой сборке и линковке. Поэтому новый формат вряд ли вытеснит все существующие varint-схемы; скорее он найдет свою нишу там, где двусмысленность опаснее, чем неудобство миграции.

Что это значит для индустрии

Для русскоязычной IT-аудитории здесь как минимум три практических вывода. Первый: безопасность бинарных протоколов все чаще решают не через наращивание числа проверок, а через пересборку самого формата данных. Второй: если ваш сервис подписывает сообщения, использует content-addressable storage, кэширует сериализованные объекты или гоняет состояние между нодами, старое доброе varint-кодирование перестает быть невидимой деталью реализации и становится архитектурным выбором. Третий: интерес к bijou64 уже не ограничился лабораторным постом. Референсная реализация опубликована на crates.io под лицензиями MIT/Apache 2.0, для JavaScript есть обертки на npm, а сообщество быстро принесло порты на Elixir, Go, Perl и Java. Когда новый формат за считаные дни получает несколько независимых реализаций, это обычно значит, что боль разработчики узнают без подсказок.

Отдельно примечательно, что Ink & Switch сразу описывает не только bijou64, но и варианты ширины bijou32 и bijou128. Это сигнал, что речь идет не о штучной оптимизации для одного протокола, а о попытке оформить семейство схем для разных диапазонов значений. Если идея приживется, следующим этапом станет не спор о красивой математике, а более скучный и важный вопрос: где такие форматы начнут появляться по умолчанию — в криптографических протоколах, системах репликации, форматах хранения или SDK для сетевых сервисов. Пока bijou64 выглядит как редкий случай, когда разговор о байтах внезапно касается не только перформанса, но и инженерной гигиены целых платформ. Подробности анонса и обсуждения собрал InfoQ.

Поделиться: Telegram X LinkedIn