DAT (Distributed Access Token)

1. Обзор

По мере роста числа одновременно подключённых пользователей растёт и количество сессий (Session), что создаёт чрезмерную нагрузку на сессионный сервер.

DAT — это спецификация токена, созданная для того, чтобы решить проблему нагрузки на сессионный сервер и реализовать эффективную аутентификацию без совместного состояния между серверами (Stateless).

DAT — это строка из 5 фиксированных полей, разделённых точкой (.). Каждое поле можно вырезать по позиции разделителя без разбора JSON, а время истечения и область шифрования включены в саму спецификацию.


2. Проводной формат

Проводной формат DAT
expire
uint64 (дес.)
.
cid
uint64 (шестн.)
.
plain
Base64Url
.
secure
Base64Url
.
signature
Base64Url
Наведите курсор на поле, чтобы увидеть описание.
expire . cid . plain . secure . signature
ПолеТипКодированиеПримечание
Время истеченияuint64десятичная строкаUnixtime (секунды)
CIDuint64шестнадцатеричная строкаID сертификата
Открытые данныеBinaryBase64Url (без заполнения)открытые данные
Зашифрованные данныеBinaryBase64Url (без заполнения)зашифрованные данные
ПодписьBinaryBase64Url (без заполнения)подпись
Структура
Примерrefresh
/

2.1. Детальная спецификация полей

Время истечения : uint64 (Unix Time)

  • Время истечения токена в виде 64-битного беззнакового целого числа в секундах (Seconds).
  • Допускаются только чистые десятичные цифры. Знак, пробелы или разделители означают ошибку формата.

CID : Hex (uint64)

  • Идентификатор сертификата (Certificate ID), используемого для проверки токена.
  • Допускаются только чистые шестнадцатеричные цифры, префикс 0x не используется.

Открытые данные : Base64Url (Binary)

  • Содержит данные, открытые для клиента. Поддерживаются не только строки, но и бинарные данные; клиент может декодировать и просмотреть их.
  • Не шифруется. Помещать сюда конфиденциальные значения нельзя.

Зашифрованные данные : Base64Url (Binary)

  • Содержит данные, скрытые от клиента. Они зашифрованы алгоритмом шифрования сертификата, поэтому клиент, не имеющий сертификата, не может расшифровать содержимое.
  • Внутренняя структура — IV(96bit) + шифротекст; IV генерируется заново при каждом шифровании.

Подпись : Base64Url (Binary)

  • Данные подписи для проверки подделки и изменения токена. Создаются подписанием предшествующих полей алгоритмом подписи сертификата.
  • Если проверка подписи не прошла, ни одному полю такого токена доверять нельзя.

3. Канонические правила (Canonical Rules)

Чтобы клиенты, реализованные на разных языках, интерпретировали один и тот же токен одинаково, приведённые ниже правила не должны расходиться между реализациями. Эталонная реализация — Rust (dat-rust), и все остальные реализации приведены в соответствие с ней.

3.1. Разбор числовых полей

expire и cid интерпретируются строго. Все приведённые ниже входные данные отклоняются как ошибка формата.

Пример вводаРезультатПричина
100приняточистое десятичное число
007принятоведущие нули допускаются
+100отклоненознак недопустим
-1отклоненознак недопустим
" 100 "отклоненопробелы недопустимы
1_0отклоненоразделители недопустимы
0x10отклоненопрефиксы недопустимы
zzzzотклоненоне число
""отклоненопустая строка
18446744073709551616отклоненовыход за диапазон uint64

Почему требуется строгость

Снисходительный парсер превращает -1 в максимальное значение uint64 и создаёт фактически неистекающий токен либо молча заменяет нечисловое значение на 0. Если снисходительность различается между реализациями, один и тот же токен в одном месте пройдёт, а в другом будет отклонён — и совместимость нарушится.

3.2. Определение истечения

У токена DAT и у сертификата границы истечения разные. Не путайте их.

ОбъектУсловие действительностиРовно в момент истечения (expire == now)
Токен DATexpire > nowотклоняется как истёкший
Сертификатexpire >= nowещё действителен

Токен становится недействительным ровно в момент истечения, а сертификат действителен до этого момента включительно. Сертификат должен жить на один тик дольше токена, чтобы можно было проверить токен, выданный на самой границе.

3.3. Пустая полезная нагрузка secure

Если шифровать нечего, secure — это пустая строка.

  • encrypt(пустой ввод) → пустой вывод (не добавляются ни IV, ни тег GCM)
  • decrypt(пустой ввод) → пустой вывод
  • Если значение непустое, но не длиннее IV (12 байт), это ошибка расшифрования.
1893456000.1a.SGVsbG8..T3RoZXItc2lnbmF0dXJl
                      ↑ корректный токен с пустым местом под secure

4. Выдача и проверка

DAT: выдача → передача → проверка
DAT CMS
Сервер выдачи
Клиент
Сервер проверки
Распространение сертификата
Распространение сертификата
Вход
issue(plain, secure)
Выдача DAT
Запрос с DAT
Поиск сертификата по CID → проверка подписи → расшифрование
Ответ
запросответсинхронизация сертификатов

4.1. Процедура выдачи

  1. Из имеющихся у менеджера сертификатов выбирается доступный для выдачи (issuable).
  2. Вычисляется expire = now + dat_ttl_seconds.
  3. plain кодируется в Base64Url, а secure сначала шифруется, затем кодируется в Base64Url.
  4. Строка expire.cid.plain.secure подписывается, и подпись добавляется последним полем.

4.2. Процедура проверки

  1. Строка разбивается точкой (.) на 5 полей. Иное количество полей — ошибка формата.
  2. Проверяется expire. Истёкший токен отклоняется до проверки подписи.
  3. По cid отыскивается сертификат. Если его нет, проверка невозможна.
  4. Подпись проверяется по участку expire.cid.plain.secure.
  5. Только после успешной проверки выполняется расшифрование secure.

Не доверяйте значениям до проверки подписи

Некоторые реализации предоставляют API, извлекающий поля без проверки подписи (семейство parse without verify). Эти значения полностью контролируются атакующим, поэтому использовать их следует только для логирования и отладки.


5. Сравнение с JWT

DAT и JWT (JSON Web Token) разделяют структуру токена, разбитого точками (.), и способ проверки через подпись, однако во внутреннем устройстве между ними есть следующие ключевые различия.

5.1. Сравнение структурных различий

  • Структура JWT

    headerbodysignature
    Base64Url (JSON String)Base64Url (JSON String)Base64Url (Binary)
  • Структура DAT

    Время истеченияCIDОткрытые данныеЗашифрованные данныеПодпись
    Unixtime (uint64)Hex (uint64)Base64Url (Binary)Base64Url (Encrypt Binary)Base64Url (Binary)

5.2. Ключевые различия

  • Облегчённость на основе Binary: JWT оперирует заголовком (Header) и телом (Body) в виде JSON-строк, тогда как DAT работает непосредственно с бинарными данными (Binary), оптимизируя размер данных и повышая эффективность разбора.
  • Встроенная безопасность (поле Зашифрованные данные): В JWT полезная нагрузка (Payload) по умолчанию передаётся в открытом виде, и при необходимости шифрования приходится применять отдельную спецификацию вроде JWE. DAT же поддерживает шифрование непосредственно в самом токене через поле Зашифрованные данные.
  • Принудительное ограничение срока действия: В JWT поле exp (Claims) необязательно, тогда как в DAT поле Время истечения закреплено в структуре токена, поэтому проверка срока действия выполняется обязательно.
  • Отсутствие согласования алгоритма: JWT носит значение alg в собственном заголовке, из-за чего возникает поверхность атаки на путаницу алгоритмов. В DAT алгоритм определяет сертификат, и в токене сведений об алгоритме нет.