Типы ContentInfo: data, signedData, envelopedData, digestedData

ContentInfo в CMS (Cryptographic Message Syntax) представляет собой контейнер верхнего уровня, который определяет формат криптографически защищённых сообщений. В библиотеке Jsrsasign он используется как основа для построения и разбора структур PKCS

ContentInfo всегда состоит из двух ключевых компонентов:

  • contentType — идентификатор типа содержимого (OID)
  • content — само содержимое, структура которого зависит от типа

В ASN.1 это выглядит следующим образом:

ContentInfo ::= SEQUENCE {
  contentType ContentType,
  content [0] EXPLICIT ANY DEFINED BY contentType
}

Тип data (id-data)

Тип data является самым простым вариантом ContentInfo. Он представляет собой «сырые» данные без криптографической защиты.

OID для data:

1.2.840.113549.1.7.1

Этот тип используется, когда сообщение инкапсулируется в CMS, но не подписывается и не шифруется.

Структура content в этом случае содержит OCTET STRING с исходными данными.

Особенности применения

  • используется как контейнер для передачи произвольных байтов
  • может быть промежуточным этапом перед подписанием или шифрованием
  • часто встречается в тестовых и учебных сценариях CMS

Jsrsasign: формирование data

const cms = new KJUR.asn1.cms.ContentInfo({
  type: "data",
  content: "616263" // hex для "abc"
});

const pem = cms.getPEM();

Внутри Jsrsasign данные кодируются как OCTET STRING и помещаются в структуру ContentInfo без дополнительных атрибутов.

Тип signedData

signedData — один из наиболее сложных и часто используемых типов CMS. Он реализует цифровую подпись с возможностью включения или исключения оригинального сообщения.

OID:

1.2.840.113549.1.7.2

Структура SignedData

SignedData включает:

  • version
  • digestAlgorithms
  • encapContentInfo
  • certificates (опционально)
  • crls (опционально)
  • signerInfos

Основная идея заключается в том, что данные могут быть либо:

  • инкапсулированными внутри структуры (encapsulated content)
  • или передаваться отдельно (detached signature)

encapContentInfo

Содержит:

  • eContentType (обычно id-data)
  • eContent (само сообщение)

signerInfos

Содержит информацию о подписи:

  • алгоритм подписи
  • сертификат подписанта
  • значение подписи
  • атрибуты (signed/unsigned)

Jsrsasign: создание signedData

const sd = new KJUR.asn1.cms.SignedData({
  content: {
    type: "data",
    data: "616263"
  },
  signerInfos: [{
    version: 1,
    sid: { type: "issdn", cert: certObj },
    hashAlg: "sha256",
    signAlg: "RSA",
    signature: "..."
  }],
  certs: [certObj]
});

const cms = new KJUR.asn1.cms.ContentInfo({
  type: "signedData",
  content: sd
});

Особенности signedData

  • обеспечивает целостность данных
  • поддерживает проверку подлинности отправителя
  • может включать цепочку сертификатов
  • позволяет detached signature (когда content отсутствует)

Тип envelopedData

envelopedData используется для шифрования данных. Он реализует гибридную криптосистему: данные шифруются симметричным алгоритмом, а ключ — асимметричным.

OID:

1.2.840.113549.1.7.3

Структура EnvelopedData

Основные компоненты:

  • version
  • recipientInfos
  • encryptedContentInfo

encryptedContentInfo

Содержит:

  • contentType
  • contentEncryptionAlgorithm
  • encryptedContent

recipientInfos

Каждый получатель имеет свою запись:

  • идентификатор сертификата
  • зашифрованный симметричный ключ
  • параметры алгоритма

Механизм работы

  1. Генерируется случайный симметричный ключ
  2. Данные шифруются (AES, 3DES и т.д.)
  3. Симметричный ключ шифруется публичным ключом каждого получателя
  4. Результат упаковывается в CMS

Jsrsasign: создание envelopedData

const ed = new KJUR.asn1.cms.EnvelopedData({
  content: {
    type: "data",
    data: "616263"
  },
  recipients: [{
    cert: certObj,
    alg: "RSA"
  }],
  symAlg: "aes256"
});

const cms = new KJUR.asn1.cms.ContentInfo({
  type: "envelopedData",
  content: ed
});

Особенности envelopedData

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

Тип digestedData

digestedData используется для хранения данных вместе с их хэш-значением. В отличие от signedData, он не содержит криптографической подписи, а только контрольную сумму.

OID:

1.2.840.113549.1.7.5

Структура digestedData

Состоит из:

  • version
  • digestAlgorithm
  • encapContentInfo
  • digest

encapContentInfo

Аналогично signedData:

  • eContentType
  • eContent

digest

Хэш значения содержимого, вычисленный по указанному алгоритму (SHA-1, SHA-256 и др.)

Назначение

  • проверка целостности без подписи
  • облегчённая альтернатива signedData
  • использование в системах, где не требуется PKI

Jsrsasign: создание digestedData

const dd = new KJUR.asn1.cms.DigestedData({
  content: {
    type: "data",
    data: "616263"
  },
  hashAlg: "sha256"
});

const cms = new KJUR.asn1.cms.ContentInfo({
  type: "digestedData",
  content: dd
});

Особенности digestedData

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

Сравнение типов ContentInfo

data

  • отсутствие защиты
  • только контейнер данных
  • минимальная структура

signedData

  • цифровая подпись
  • проверка подлинности
  • сложная структура с сертификатами

envelopedData

  • шифрование содержимого
  • защита конфиденциальности
  • гибридная криптосистема

digestedData

  • контроль целостности через хэш
  • отсутствие подписи
  • облегчённая структура CMS

Внутренняя реализация в Jsrsasign

В Jsrsasign CMS реализован через набор ASN.1 классов:

  • KJUR.asn1.cms.ContentInfo
  • KJUR.asn1.cms.SignedData
  • KJUR.asn1.cms.EnvelopedData
  • KJUR.asn1.cms.DigestedData

Каждый класс отвечает за формирование соответствующей ASN.1 структуры и кодирование её в DER/PEM формат.

Общий принцип построения:

  1. Формирование внутренней структуры (SignedData, EnvelopedData и т.д.)
  2. Оборачивание в ContentInfo
  3. Кодирование в DER
  4. При необходимости — PEM-конвертация

Пример разбора ContentInfo

const ci = KJUR.asn1.cms.ContentInfo.fromPEM(pemString);

if (ci.contentType === "signedData") {
  const sd = ci.content;
}

Особенности работы с OID в CMS

Каждый тип ContentInfo строго идентифицируется OID:

  • data → 1.2.840.113549.1.7.1
  • signedData → 1.2.840.113549.1.7.2
  • envelopedData → 1.2.840.113549.1.7.3
  • digestedData → 1.2.840.113549.1.7.5

Jsrsasign использует эти OID для автоматического выбора парсера и интерпретации структуры.

Взаимодействие типов внутри CMS

ContentInfo может содержать только один тип данных, однако на практике структуры часто комбинируются:

  • signedData может включать envelopedData как контент
  • envelopedData может защищать signedData
  • digestedData может использоваться до подписи как промежуточный слой контроля

Такая вложенность позволяет строить сложные криптографические протоколы поверх CMS, сохраняя совместимость с PKCS#7 и RFC 5652.