Кратко

  • Composite ML-DSA считает проверку успешной лишь тогда, когда верны обе компоненты. В CMS при этом отдельно указаны дайджест, алгоритм подписи и защищённые атрибуты. Их расхождение нельзя скрывать за общим зелёным статусом.
  • Получатель должен восстановить именно подписанные байты, заново вычислить хеш содержимого и сопоставить все AlgorithmIdentifier. Проверка сертификата, полномочий подписанта и фактического результата операции остаётся отдельной частью решения.

Криптографическая библиотека вернула два успеха. Подпись ML-DSA сошлась, классическая подпись тоже. Однако поле SignerInfo.digestAlgorithm указывало дайджест, который не соответствует составному алгоритму в signatureAlgorithm.

Это не спор о названиях. Если приложение принимает математический результат и игнорирует противоречие конверта, оно уже не может доказать, какой набор правил применило. А если журнал сохраняет лишь фразу «постквантовая подпись действительна», то после события восстановить решение будет невозможно.

Именно эту границу уточняет редакция 05 проекта LAMPS Composite Module-Lattice-Based Digital Signature Algorithm (ML-DSA) for use in Cryptographic Message Syntax (CMS). Документ датирован 22 мая 2026 года, действует до 23 ноября и нацелен на Proposed Standard. 1 октября Datatracker перевёл его в очередь RFC Editor с ожиданием второго редактора. Это важный этап процесса, но ещё не RFC и не свидетельство внедрения, настройки или совместимости продуктов.

Единый алгоритм не отменяет поля CMS

Связанный проект Composite ML-DSA соединяет ML-DSA с RSA, ECDSA, Ed25519 либо Ed448. Для протокола это один открытый ключ, одна подпись и одна операция проверки. Успех возможен только при успехе каждой компоненты. Такая конструкция избавляет приложения от самодельной логики «две подписи рядом».

Но CMS уже содержит собственную систему утверждений. В SignedData.digestAlgorithms перечислены применяемые дайджесты. Каждый SignerInfo содержит digestAlgorithm и signatureAlgorithm. В подписанных атрибутах может находиться CMSAlgorithmProtection. Сертификат, в свою очередь, описывает алгоритм открытого ключа.

Эти координаты нельзя свести к одному ярлыку. Надёжный протокол проверки должен отдельно записывать составной OID, алгоритм ключа сертификата, оба идентификатора из SignerInfo, наличие параметров, значения защищённого атрибута и результат каждой компоненты. Только затем политика может подтвердить, что объект не просто математически проверился, а был интерпретирован одинаково всеми слоями.

Редакция 05 перечисляет 18 OID для сочетаний параметров ML-DSA и традиционных схем. В signatureAlgorithm параметры должны отсутствовать. Явный NULL не является безобидной альтернативой, когда профиль требует отсутствующего поля: различие входит в проверяемый контракт кодирования.

Составной OID заранее выбирает дайджест

Для CMS этот профиль Composite ML-DSA использует только режим предварительного хеширования. Каждому составному алгоритму назначен конкретный внешний дайджест: SHA-256, SHA-512 или SHAKE256. Поэтому SignerInfo.digestAlgorithm обязан совпасть с выбором, зафиксированным OID подписи.

Правило включает параметры AlgorithmIdentifier. Для SHA-256 и SHA-512 они должны отсутствовать. Для SHAKE256 они тоже отсутствуют, а размер результата составляет 64 байта. Реализация, которая молча принимает лишний NULL, не проявляет гибкость — она стирает различие, которое профиль сделал наблюдаемым.

Внутри традиционной компоненты может использоваться иной дайджест. Например, ECDSA P-384 способен работать с SHA-384, тогда как внешний предварительный хеш составного алгоритма равен SHA-512. Это корректно: речь идёт о разных уровнях. Операционные журналы должны маркировать уровень каждого имени, иначе нормальное различие выглядит ошибкой, а настоящее внешнее расхождение остаётся незамеченным.

Набор SignedData.digestAlgorithms должен содержать соответствующий дайджест, чтобы однопроходный получатель заранее подготовил вычисление. Его отсутствие способно сорвать такую проверку. Но наличие элемента в общем наборе не заменяет обязательное совпадение для конкретного SignerInfo. Набор описывает коллекцию, а поле подписанта — его собственное действие.

Подписываемые байты зависят от наличия атрибутов

Если подписанных атрибутов нет, операция охватывает значение OCTET STRING из eContent, без байтов тега и длины. Когда атрибуты присутствуют, подписывается уже не содержимое напрямую, а полная DER-кодировка SignedAttrs, включая тег и длину.

Здесь есть важная деталь. В готовом SignerInfo атрибуты записаны с IMPLICIT-тегом [0], но вход подписи строится с EXPLICIT-тегом SET OF. Нельзя просто взять видимый фрагмент исходного объекта или повторно сериализовать разобранную структуру произвольным ASN.1-кодером. Нужно воспроизвести строго заданную последовательность байтов.

Минимальный набор подписанных атрибутов содержит content-type и message-digest. Получатель обязан самостоятельно вычислить хеш инкапсулированного содержимого и сравнить его со значением атрибута. Корректная подпись над атрибутами ещё не доказывает связь с выданным содержимым, если это сравнение пропущено.

Поэтому доказательная запись начинается с хеша неизменённого CMS-объекта. Затем фиксируются хеш извлечённого содержимого, хеш точной DER-последовательности атрибутов, полученный и вычисленный заново message-digest, а также диапазон байтов, переданный в Composite ML-DSA. Нормализованное JSON-представление или дерево ASN.1 полезны для анализа, но не заменяют оригинал.

У базовой криптографической конструкции есть вход контекста. В CMS-профиле он жёстко равен пустой строке. Следовательно, приложение не может приписать разграничение операций скрытому непустому контексту примитива. Назначение должно вытекать из проверенного типа содержимого, подписанных атрибутов, политики сертификата или другого явно подтверждённого правила.

История алгоритма должна быть подписана

RFC 6211 определил CMSAlgorithmProtection: в подписанные атрибуты включаются дайджест и алгоритм подписи либо MAC. Редакция 05 рекомендует этот атрибут для защиты от подмены алгоритма, а RFC 8933 усиливает требования согласованности дайджестов CMS.

Преимущество не в ещё одном поле, а в том, что поле попадает в защищённый байтовый диапазон. Внешний AlgorithmIdentifier можно изменить, не меняя криптографический вход. Если те же значения находятся в подписанном атрибуте, проверяющий сопоставляет внутреннее утверждение подписанта с внешними полями и составным OID.

Наличие атрибута само по себе ничего не разрешает. Надо проверить его структуру, число экземпляров, допустимые значения, отсутствие запрещённых параметров и совместимость с ключом сертификата. Формулировка SHOULD допускает профили, где отсутствие атрибута разрешено, однако этот факт должен остаться отдельной координатой политики, а не исчезнуть в общем ответе «успешно».

Решение должно давать ответы на конкретные вопросы. Были ли подписанные атрибуты? Был ли CMSAlgorithmProtection внутри защищённой части? Совпал ли его дайджест с SignerInfo.digestAlgorithm? Совпала ли подпись с составным OID? Отсутствовали ли параметры там, где требуется? Подходил ли ключ сертификата? Прошли ли обе компоненты? Совпал ли пересчитанный хеш содержимого?

Номер реестра не равен опубликованному стандарту

Проект запрашивает один идентификатор SMI Security для ASN.1-модуля. В тексте редакции 05 ещё стоит издательский заполнитель. Между тем публичный реестр IANA, зафиксированный 2 октября, уже показывает десятичное значение 88 для id-mod-composite-mldsa-cms-2026 и ссылается на проект.

Эти сведения не конфликтуют. Реестр уже содержит назначение, сохранённая редакция текста ещё не получила окончательную подстановку, а документ проходит очередь RFC Editor. Ни один из этих фактов не превращает проект в опубликованный RFC автоматически.

Также номер не доказывает поддержку библиотек, выпуск подходящих сертификатов, включение алгоритма оператором или успешную обработку реальных объектов. Для значения модуля источником служит актуальный публичный реестр. Для статуса стандарта — Datatracker и будущая публикация RFC. Для внедрения нужны наблюдения из работающей системы.

Две верные компоненты не выдают полномочия

Составная конструкция требует успеха обеих подписей. Она также запрещает повторно использовать компоненты ключа в других контекстах. Генерация, HSM, резервное копирование, ротация и уничтожение должны сохранять эту границу, даже если инвентарь показывает пару как один управляемый объект.

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

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