Перейти к содержанию

ASN.1, DER и OID: чтение внутреннего формата CMS

Зачем специалисту знать ASN.1

CMS — не произвольный поток зашифрованных байтов. Он содержит вложенные структуры ASN.1: SEQUENCE, SET, INTEGER, OCTET STRING, OBJECT IDENTIFIER. В ASN.1 определены типы полей, а DER/BER описывают правила записи значений в байты. По этим правилам можно последовательно разобрать сообщения, сертификаты и записи алгоритмов.

Самый важный для совместимости тип — OBJECT IDENTIFIER (OID). Это числовой путь в пространстве имен, например 1.2.643.2.2.21, обозначающий ГОСТ 28147-89 в старом CMS-профиле. OID не содержит сам криптографический алгоритм: он только позволяет программе выбрать заранее реализованный код и корректно прочитать параметры.

Примеры OID из рассматриваемых документов

OID Назначение Источник
1.2.643.2.2.9 ГОСТ Р 34.11-94 RFC 4490 §2
1.2.643.2.2.10 HMAC по ГОСТ Р 34.11-94 RFC 4490 §6
1.2.643.2.2.21 ГОСТ 28147-89 RFC 4490 §5
1.2.643.7.1.1.2.2 ГОСТ Р 34.11-2012/256 Проект ТК26 §4
1.2.643.7.1.1.2.3 ГОСТ Р 34.11-2012/512 Проект ТК26 §4
1.2.643.7.1.1.4.1 HMAC Стрибог-256 Проект ТК26 §8
1.2.643.7.1.1.4.2 HMAC Стрибог-512 Проект ТК26 §8

Наличие знакомого OID внутри DER не гарантирует, что приложение знает также нужные параметры и режим. Кроме того, поле алгоритма должно интерпретироваться в контексте структуры: один OID в SignerInfo и другой в EncryptedContentInfo отвечают за разные операции.

Три вида кодировки, которые часто путают

DER — бинарное представление ASN.1 с однозначными правилами кодирования. Многие файлы .p7s/.p7m хранятся именно так.

PEM — текстовая броня Base64 с границами BEGIN … и END …; внутри может находиться DER-представление определённого ASN.1-объекта. Сам по себе PEM не говорит, что внутри подпись ГОСТ.

S/MIME — формат MIME-сообщения с заголовками, типами содержимого и, в зависимости от режима, вложенным CMS. Почтовый файл .eml нельзя без проверки подавать в программу, ожидающую чистый бинарный DER.

Как прочитать реальный контейнер

Для файла document.p7s, полученного из доверенного источника, сначала проверьте внешний тип формата и структуру:

file document.p7s
openssl asn1parse -inform DER -in document.p7s -i | head -80

openssl asn1parse показывает низкоуровневые поля. Для полноценной расшифровки смысла структуры используйте CMS-декодер:

openssl cms -cmsout -print -inform DER -in document.p7s -noout

Это команды просмотра, а не проверки криптографической подписи и не решения вопроса доверия сертификату. В openssl cms -verify должны быть заданы правильные сертификаты, доверенная цепочка и, при необходимости, исходный документ для detached-подписи. Подробный процесс: OpenSSL CMS.

Почему нельзя просто искать байты с OID

У ASN.1 есть длины, вложенные контейнеры и контекстные теги. Совпадение последовательности байтов внутри зашифрованного содержимого или неподходящего вложенного объекта не доказывает, что именно этот алгоритм использован для подписи. Нужно разбирать дерево ASN.1 и определять OID в соответствующем поле: например, SignerInfo.signatureAlgorithm либо EncryptedContentInfo.contentEncryptionAlgorithm.

Дополнительно BER и DER отличаются по правилам допустимого представления. Если программа повторно кодирует подписанные атрибуты неканонично, байты проверяемой подписи могут измениться. Для SignedData особенно важны правила DER-кодирования signedAttrs в RFC 5652.

Практический пример для чтения шестнадцатеричных данных

В проекте ТК26, раздел 9, приведён DER-фрагмент SMIMECapability для Стрибог-256:

30 0A 06 08 2A 85 03 07 01 01 01 01

Первый байт 30 обозначает SEQUENCE, 0A — длину вложенного содержимого, 06 — тип OBJECT IDENTIFIER, 08 — длину значения OID. Это удобный короткий пример того, что ASN.1 состоит из тегов и длин, а не из текстовых названий алгоритмов. Следующий шаг — декодировать байты OID и сопоставить их с таблицей спецификации.

TLV и каноничность: что видит декодер

В BER/DER объект записывается как тег → длина → значение (TLV). ASN.1 определяет структуру и типы, BER допускает некоторые альтернативные кодировки, а DER устанавливает более строгие правила однозначного представления. Это важно прежде всего для подписанных атрибутов CMS: при разной сериализации одной логической структуры меняются подписанные байты.

30 0A                       SEQUENCE, длина 10
   06 08                    OBJECT IDENTIFIER, длина 8
      2A 85 03 07 01 01 01 01   закодированные дуги OID

Указанный набор байт — образец чтения TLV, а не готовое доказательство назначения OID в любом сообщении. Имя алгоритма определяется его положением в конкретном ASN.1-типе и соответствующей спецификацией.

Почему у одного алгоритма несколько OID

Разные идентификаторы могут относиться к хэш-функции, алгоритму подписи с хэшем, типу открытого ключа, параметрам эллиптической кривой, режиму шифрования или алгоритму переноса ключа. Это разные объекты! Чтение 1.2.643... без понимания поля — только первый шаг. Сверяйте терминологию с RFC 9215 (X.509), RFC 4490 (исторический CMS) и каталогом OID НАЙС.ОС.

Порядок байтов, битов и компонентов подписи

У ГОСТ-криптографии ошибки совместимости часто происходят не на уровне вычисления эллиптических операций, а при упаковке в ASN.1: байтовый порядок координат открытого ключа, порядок компонентов r/s, фиксированная длина и кодировка параметров. Нельзя выводить из одного профиля X.509 формат CMS или формат прикладного API. Для X.509 см. RFC 9215 §4, для прикладной интеграции — форматы подписей.

Методика исследования без «магических» подмен

# Пример для локального файла; только просмотр, без записи результата.
file document.p7s
openssl asn1parse -inform DER -in document.p7s -i | head -n 100
openssl cms -cmsout -print -inform DER -in document.p7s -noout

Третья команда декодирует смысл CMS-полей, но не подтверждает подпись. Если файл PEM или содержит MIME-заголовки, нужно выбрать соответствующий входной формат, а не считать сообщение испорченным. Обратите внимание, что asn1parse может показывать BER-содержимое; задача криптографической проверки signedAttrs — применять требования DER, а не переписывать весь контейнер.

Что фиксировать в протоколе испытаний

Поле протокола Что записывать
Тип внешнего контейнера ContentInfo.contentType, файл/URI
Подпись SignerInfo.digestAlgorithm, signatureAlgorithm, sid
Сертификат алгоритм subjectPublicKeyInfo, кривая, serial, issuer
Шифрование EncryptedContentInfo.contentEncryptionAlgorithm, параметры
Получатель вид RecipientInfo, управление CEK, UKM
Представление DER/BER/PEM/MIME, байтовые длины
Проверка parse / crypto / chain / revocation / policy

Проверенные практические сценарии: OpenSSL CMS, диагностика контейнера, GPGSM, план межоперабельности.

Источники


Маршрут чтения: Контейнеры CMS → Матрица совместимости → Диагностика