Всо 690

Бесплатная консультация юриста

+7 (800) 301-07-30

Реклама jurik.ru

X.690 — это фундаментальный стандарт телекоммуникационного сектора Международного союза электросвязи (МСЭ-Т / ITU-T), совместно разработанный с Международной организацией по стандартизации (ИСО / ISO) и Международной электротехнической комиссией (МЭК / IEC). Стандарт определяет правила преобразования абстрактных структур данных, описанных на языке ASN.1 (Abstract Syntax Notation One), в конкретные последовательности байтов (октетов) для передачи по сетям связи или хранения в файлах.

Актуальная версия стандарта соответствует ISO/IEC 8825-1. Ранее (до 1994 года) данные правила были частью рекомендации X.209, однако с переходом на серию рекомендаций X;680/X.690 они были выделены в отдельный документ.


Назначение и область применения

Главная цель X.690 — обеспечить платформонезависимое представление данных. Разные компьютерные архитектуры используют разный порядок байтов (endianness), разные форматы чисел с плавающей точкой и строк. X.690 устраняет эти различия, задавая строгие правила сериализации.

  • Интероперабельность: Позволяет системам на разных языках (C, Java, Python, Go) и ОС обмениваться сложными структурами данных.
  • Телекоммуникации: База для протоколов SNMP, LDAP, X.509 (сертификаты PKI), H.323, SIP, MAP (GSM/UMTS), Diameter и многих других;
  • Хранение: Используется для сохранения конфигураций, логов и баз данных в бинарном виде.

Три набора правил кодирования

Стандарт X.690 описывает три основных набора правил (Encoding Rules), различающихся степенью строгости и областью применения:

Аббревиатура Полное название Характеристика Основное применение
BER Basic Encoding Rules (Базовые правила кодирования) Гибкие, позволяют несколько способов кодирования одного значения (например, разная длина поля длины, неопределенная длина для составных типов). Общие цели, отладка, протоколы, где важна простота кодировщика/декодировщика.
CER Canonical Encoding Rules (Канонические правила кодирования) Подмножество BER. Жестко фиксирует один способ кодирования для каждого типа. Использует неопределенную длину для больших составных объектов. Редко используется напрямую; исторически для криптографии (заменен DER).
DER Distinguished Encoding Rules (Особые/Различительные правила кодирования) Строгое подмножество BER. Гарантирует уникальное бинарное представление для каждого значения. Запрещает неопределенную длину, требует минимальной длины поля длины, сортировку SET по тегам. Криптография, цифровые подписи, сертификаты X.509, блокчейн. Критично, когда хэш от данных должен быть детерминированным.

Структура кодированного блока: TLV

Вся архитектура X.690 строится на принципе TLV (Tag-Length-Value) — Тег, Длина, Значение. Любой закодированный элемент данных состоит из трех последовательных полей:

  1. Identifier (Идентификатор / Тег) — определяет тип данных и класс.
  2. Length (Длина) — указывает количество октетов в поле Value.
  3. Contents (Значение / Содержимое) — сами закодированные данные.

Поле Identifier (Тег)

Первый октет идентификатора имеет следующую битовую структуру:

Биты: 8 7 6 5 4 3 2 1
 +---+---+---+---+---+---+---+---+
 | Класс | П/К | Номер тега | (короткая форма, тег 0..30)
 +---+---+---+---+---+---+---+---+

Класс тега (Биты 8-7)

  • 00, Universal (Универсальный): Типы, определенные в самом стандарте X.690 (INTEGER, SEQUENCE, OCTET STRING и т.д.). Смысл одинаков во всех приложениях.
  • 01 — Application (Прикладной): Типы, смысл которых зависит от конкретного протокола/приложения (например, в SNMP: GetRequest, GetResponse).
  • 10 — Context-specific (Контекстно-зависимый): Типы, смысл которых определен внутри конкретной структуры (например, поля внутри SEQUENCE, помеченные [0], [1]…).
  • 11 — Private (Частный): Типы, определенные конкретной организацией (Enterprise numbers).

Тип кодирования (Бит 6 — P/C бит)

  • 0 — Primitive (Примитивное): Значение кодируется напрямую (INTEGER, BOOLEAN, NULL, строки).
  • 1 — Constructed (Конструктивное): Значение содержит в себе другие TLV-блоки (SEQUENCE, SET, SEQUENCE OF, явная маркировка EXPLICIT).

Номер тега (Биты 5-1)

Если номер тега 0..30, он помещается в биты 5-1 первого октета.

Если номер тега > 30, используется длинная форма:

  • Биты 5-1 первого октета устанавливаются в 11111 (0x1F).
  • Последующие октеты кодируют номер тега по 7 бит (бит 8 = 1 для продолжения, бит 8 = 0 для последнего октета).

Таблица основных универсальных тегов (Universal Class)

Тип данных ASN.1 Номер тега (дек) Номер тега (hex) Примитив/Конструктив HEX Тег (Primitive)
EOC (End-of-Content) 0 0x00 Prim 0x00
BOOLEAN 1 0x01 Prim 0x01
INTEGER 2 0x02 Prim 0x02
BIT STRING 3 0x03 Prim/Constr 0x03
OCTET STRING 4 0x04 Prim/Constr 0x04
NULL 5 0x05 Prim 0x05
OBJECT IDENTIFIER (OID) 6 0x06 Prim 0x06
ENUMERATED 10 0x0A Prim 0x0A
UTF8String 12 0x0C Prim 0x0C
SEQUENCE / SEQUENCE OF 16 0x10 Constr 0x30
SET / SET OF 17 0x11 Constr 0x31
PrintableString 19 0x13 Prim 0x13
IA5String (ASCII) 22 0x16 Prim 0x16
UTCTime 23 0x17 Prim 0x17
GeneralizedTime 24 0x18 Prim 0x18
BMPString (UCS-2) 30 0x1E Prim 0x1E

Примечание: Для конструктивных типов (SEQUENCE, SET) к базовому тегу добавляется бит 6 (0x20), поэтому SEQUENCE = 0x30, SET = 0x31.

Поле Length (Длина)

Кодирует количество октетов в поле Value.

  • Короткая форма (Short form): Бит 8 = 0. Биты 7-1 содержат длину (0..127 байт). Пример: 0x05 — длина 5.
  • Длинная форма (Long form): Бит 8 = 1. Биты 7-1 содержат количество последующих октетов длины (1..126). Следующие октеты представляют длину как big-endian целое число.
    • Пример: 0x82 0x01 0x00 — 2 октета длины (0x0100 = 256 байт).
  • Неопределенная длина (Indefinite length): 0x80. Разрешен только в BER/CER для конструктивных типов. Завершается специальным маркером EOC (End-of-Content) — два нулевых октета 0x00 0x00. В DER запрещено.

Примеры кодирования

Пример 1: INTEGER (Примитивный тип)

Значение: 127 (0x7F)

TLV: 02 01 7F
Tag: 02 (Universal, Primitive, Tag=2 INTEGER)
Len: 01 (Short form, length=1)
Val: 7F (Value = 127)

Значение: -1 (0xFF в дополнительном коде)

TLV: 02 01 FF

Пример 2: SEQUENCE (Конструктивный тип)

ASN.1 схема:

MySeq ::= SEQUENCE {
 id INTEGER,
 name UTF8String
}

Данные: id = 1, name = "test"

30 0C -- SEQUENCE, длина 12 байт (конструктивный тег 0x10 | 0x20 = 0x30) -2 01 01 -- INTEGER id = 1
 0C 04 74 65 73 74 -- UTF8String "test" (тег 0x0C, длина 4, байты 't','e','s','t')

Пример 3: Контекстно-зависимая маркировка (IMPLICIT/EXPLICIT)

Схема: [0] IMPLICIT INTEGER внутри SEQUENCE.

-- IMPLICIT: тег заменяет универсальный тег INTEGER (0x02) на контекстный [0] (0x80)
-- Класс Context (01), Primitive (0), Tag 0 -> 1000 0000 = 0x80
80 01 05 -- Значение 5 с тегом [0]

Схема: [1] EXPLICIT INTEGER.

-- EXPLICIT: добавляется внешний обертка-тег [1] (Constructed), внутри лежит обычный INTEGER
A1 03 -- Context (01), Constructed (1), Tag 1 -> 1010 0001 = 0xA1. Len=3
 02 01 0A -- Внутри: UNIVERSAL INTEGER (0x02), Len=1, Val=10

Ключевые различия BER, CER и DER (Критически важно для разработчиков)

Правило BER CER DER
Уникальность кодирования Нет (множество вариантов) Да (каноническая форма) Да (строгая уникальная форма)
Длина для примитивов Короткая или длинная Короткая (если <128), иначе длинная Минимально необходимая (короткая если <128, иначе длинная без ведущих нулей)
Длина для конструктивных Короткая, длинная или неопределенная (0x80) Неопределенная (0x80 + EOC), если длина > 1000 байт, иначе определенная Только определенная (короткая или длинная). Неопределенная ЗАПРЕЩЕНА.
Порядок элементов SET Любой (как задал отправитель) По возрастанию тегов По возрастанию тегов
BIT STRING / OCTET STRING (фрагментация) Могут быть разбиты на части (конструктивная форма) Обязательно фрагментированы на куски по 1000 байт (конструктивная) Всегда примитивные (один кусок)
STRING типы (UTF8, GeneralString и др.) Могут быть конструктивными Конструктивные (фрагменты) Всегда примитивные
Использование в криптографии Неподходит (хэш будет разным) Подходит, но устарел Стандарт де-факто (X.509, CMS, JWT, Blockchain)

Типичные ошибки и подводные камни

  1. Нарушение DER при подписании: Использование BER-энкодера для формирования TBSCertificate (To Be Signed Certificate) приводит к тому, что проверка подписи не пройдет на строгих валидаторах (OpenSSL, Windows CryptoAPI, Java keytool), так как они ожидают строгий DER.
  2. Порядок в SET OF: В DER элементы SET OF обязательно должны быть отсортированы по тегам (лексикографически по байтам TLV). Несортированный SET — это валидный BER, но невалидный DER.
  3. Ведущие нули в INTEGER: DER требует минимальной длины. 02 02 00 01 (два байта значения) — невалидный DER для числа 1. Валидный: 02 01 01. Однако для отрицательных чисел старший бит должен быть 1 (знаковое расширение).
  4. Неопределенная длина в DER: Попытка декодировать поток с неопределенной длиной как DER должна вызывать ошибку.
  5. IMPLICIT vs EXPLICIT: Неправильная интерпретация тегов при ручном парсинге или неверная ASN.1 схема приводит к сдвигу парсинга и чтению мусора.

Инструменты для работы с X.690 / ASN.1

  • OpenSSL (asn1parse): Стандарт де-факто для разбора сертификатов и DER-блоков.
    openssl asn1parse -in cert.pem -inform pem -i
  • dumpasn1 (Peter Gutmann): Отличная утилита для глубокого разбора неизвестных бинарных блобов с выводом структуры.
  • ASN.1 Compiler (asn1c, OSS Nokalva, Objective Systems): Генерация кода (C/C++, Java, C#, Python) из .asn схем.
  • Python библиотеки: pyasn1 (чистый Python), asn1crypto (быстрый, фокус на криптографию), pyasn1-modules (готовые схемы RFC).
  • Online декодеры: lapo.it/asn1js (удобно для быстрой проверки base64/hex дампов в браузере).

Безопасность и лучшие практики

  • DoS через рекурсию: Злоумышленник может передать глубоко вложенную структуру (SEQUENCE в SEQUENCE…), вызвав переполнение стека при рекурсивном парсинге. Всегда лимитируйте глубину вложенности (например, max depth = 64 или 128).
  • DoS через длину: Поле длины в BER может указывать на гигантский размер (например, 2 ГБ), хотя реальных данных нет. Проверяйте доступные байты в буфере перед аллокацией памяти.
  • Неканоническое кодирование: При проверке цифровых подписей всегда требовать DER. Никогда не подписывайте/не проверяйте BER-данные напрямую.
  • Парсинг OID: OID кодируется специфическим образом (первые два арка в первом байте, затем base-128). Ошибки в декодере OID могут привести к подмене идентификаторов алгоритмов.

Стандарт X.690 (ISO/IEC 8825-1) остается невидимым, но критически важным фундаментом современной цифровой инфраструктуры. От TLS-хендшейков в браузере до SNMP-мониторинга серверов и сигнализации в 5G-сетях — везде работает TLV-машина, описанная в этом документе.

Понимание различий между BER (гибкость), CER (каноничность для потоков) и DER (детерминизм для криптографии) является обязательным навыком для инженеров, работающих с протоколами, PKI и безопасностью информации. Использование проверенных библиотек и строгая валидация входящих бинарных данных — залог устойчивости систем к ошибкам и атакам.


Статья подготовлена на основе материалов ITU-T X.690 (08/2015), ISO/IEC 8825-1:2015 и открытых источников (Wikipedia, RFC 5280, RFC 3279). Дата актуализации: .