Разбор ASN.1 с помощью ASN1HEX

ASN.1 в криптографических структурах чаще всего представляется в бинарном виде (DER/BER), где каждый элемент кодируется как последовательность байтов: тип, длина и значение. В библиотеке Jsrsasign для работы с таким представлением используется модуль ASN1HEX, который позволяет разбирать ASN.1 напрямую из шестнадцатеричной строки без предварительного преобразования в сложные объекты.

Любой ASN.1 элемент в DER-кодировке имеет форму:

  • Tag (тип) — один или несколько байтов
  • Length (длина) — определяет размер значения
  • Value (значение) — вложенные данные или конечное значение

В HEX-представлении это выглядит как непрерывная строка, например:

30 0a 02 01 01 02 01 05

где:

  • 30 — SEQUENCE
  • 0a — длина
  • далее идут вложенные элементы

ASN1HEX работает именно с такими строками, игнорируя необходимость предварительного декодирования.


Получение структуры ASN.1 через getPosArrayOfChildren

Основной метод для анализа вложенной структуры:

ASN1HEX.getPosArrayOfChildren(hex, pos)

Функция возвращает массив позиций дочерних элементов внутри ASN.1 структуры.

  • hex — строка ASN.1 в HEX
  • pos — позиция текущего элемента

Пример:

var hex = "300a020101020105";
var childPos = ASN1HEX.getPosArrayOfChildren(hex, 0);

Результат содержит индексы начала дочерних элементов внутри SEQUENCE.

Этот механизм позволяет рекурсивно обходить ASN.1 дерево без преобразования в объектную модель.


Определение границ элементов

Для навигации по ASN.1 структуре используются методы определения границ узлов.

getPosOfNextSibling

ASN1HEX.getPosOfNextSibling(hex, pos)

Возвращает позицию следующего элемента на том же уровне вложенности.

Принцип работы:

  • анализируется длина текущего элемента
  • вычисляется смещение до следующего sibling-узла

Пример использования:

var nextPos = ASN1HEX.getPosOfNextSibling(hex, pos);

Этот метод особенно полезен при линейном обходе структуры без построения дерева.


Определение длины и содержимого узла

ASN1HEX предоставляет низкоуровневые функции для извлечения параметров элемента.

getUint8

Позволяет получить значение байта в позиции.

getHexOfTLV

ASN1HEX.getHexOfTLV(hex, pos)

Возвращает полный TLV-блок (Tag-Length-Value) элемента.

Это важно при копировании или пересборке ASN.1 структуры.


Разбор вложенных структур

ASN.1 по своей природе рекурсивен. Каждый SEQUENCE может содержать другие SEQUENCE, SET или примитивные типы.

Типичный алгоритм обхода:

  1. Определение текущего узла
  2. Получение детей через getPosArrayOfChildren
  3. Рекурсивный вызов для каждого дочернего элемента

Пример:

function parseASN1(hex, pos) {
    var children = ASN1HEX.getPosArrayOfChildren(hex, pos);

    if (children.length === 0) {
        return ASN1HEX.getHexOfTLV(hex, pos);
    }

    var result = [];
    for (var i = 0; i < children.length; i++) {
        result.push(parseASN1(hex, children[i]));
    }
    return result;
}

Такой подход позволяет восстановить логическую структуру сертификатов X.509, ключей и других криптографических объектов.


Определение типа узла

ASN.1 использует TAG для идентификации типа данных. Jsrsasign позволяет извлекать тег через анализ первого байта:

  • 02 — INTEGER
  • 03 — BIT STRING
  • 04 — OCTET STRING
  • 30 — SEQUENCE

Проверка типа часто выполняется вручную:

var tag = hex.substr(pos * 2, 2);

Далее логика ветвится в зависимости от значения тега.


Извлечение значения узла

Для получения только значения без TLV используется:

ASN1HEX.getHexOfV(hex, pos)

Результат:

  • только содержимое Value
  • без Tag и Length

Это особенно полезно при работе с:

  • RSA модулем
  • ECDSA ключами
  • X.509 сертификатами

Поиск элементов по пути

ASN1HEX поддерживает навигацию по структуре через индексные пути.

Метод:

ASN1HEX.getVbyList(hex, pos, [index1, index2, ...])

Позволяет извлечь значение по цепочке вложенности.

Пример:

var value = ASN1HEX.getVbyList(hex, 0, [0, 1]);

Это означает:

  • первый дочерний элемент
  • затем его второй дочерний элемент

Подход упрощает доступ к глубоко вложенным структурам без ручного обхода дерева.


Определение длины элемента

ASN1HEX.getLengthOfL_AtObj(hex, pos)

Возвращает длину поля Length, что важно для корректного смещения при парсинге.

ASN.1 использует переменную длину кодирования, поэтому длина может занимать 1 или несколько байтов.


Практика анализа X.509 сертификата

ASN1HEX часто применяется для разбора сертификатов:

var certHex = "30...";
var tbsCertPos = ASN1HEX.getPosArrayOfChildren(certHex, 0)[0];

Далее:

  • извлекается Subject
  • извлекается Issuer
  • анализируется Public Key Info

Каждый блок представляет собой вложенный SEQUENCE, доступный через позиционную навигацию.


Особенности работы с DER и BER

ASN1HEX ориентирован на DER-представление, где структура однозначна:

  • нет неопределённой длины
  • нет альтернативных кодировок

BER допускает вариативность, что усложняет парсинг. В контексте Jsrsasign обычно предполагается DER.


Ошибки при разборе ASN.1

Типичные проблемы:

  • неверная позиция узла
  • неправильный расчёт длины
  • попытка интерпретации не-SEQUENCE как контейнера
  • смещение из-за многобайтового Length

Для диагностики используется:

ASN1HEX.dump(hex)

Он выводит структурное представление ASN.1 дерева, облегчая отладку.


Внутренняя модель работы ASN1HEX

Библиотека не строит объектное дерево. Вместо этого используется:

  • позиционный доступ по HEX строке
  • арифметика смещений
  • ленивый парсинг (on-demand)

Это делает ASN1HEX эффективным для больших структур, таких как сертификаты и ключевые контейнеры, где построение полноценного дерева было бы избыточным.


Рекурсивный обход и производительность

ASN1HEX оптимизирован для минимальных операций:

  • отсутствие аллокации объектов
  • работа с подстроками
  • вычисление границ через offset arithmetic

При глубоком анализе криптографических структур рекурсия остаётся основным инструментом, но контролируемая глубина обхода предотвращает избыточные вычисления.


Использование в криптографических сценариях

ASN1HEX применяется при:

  • разборе X.509 сертификатов
  • извлечении RSA ключевых параметров (modulus, exponent)
  • анализе ECDSA ключей
  • работе с PKCS#1 и PKCS#8 структурами

Каждый из этих форматов основан на ASN.1, что делает ASN1HEX универсальным инструментом низкоуровневого анализа.


Работа с вложенными SEQUENCE

SEQUENCE является базовым контейнером ASN.1. Его разбор через ASN1HEX:

  • определение позиции SEQUENCE
  • получение детей
  • рекурсивный обход

SEQUENCE может содержать:

  • другие SEQUENCE
  • SET
  • примитивные значения

Гибкость структуры требует строгого контроля позиций, так как отсутствует именованная навигация.


Особенности позиционной модели

Вся работа ASN1HEX строится вокруг концепции:

  • позиция = индекс байта в HEX-строке
  • смещение вычисляется через длину TLV
  • вложенность определяется структурой тегов

Такая модель ближе к работе с бинарными потоками, чем к объектной модели данных, что обеспечивает высокую производительность при минимальном уровне абстракции.