PKCS#7: предшественник CMS

PKCS

Структура PKCS#7 и базовые принципы

PKCS#7 описывает синтаксис для создания объектов, содержащих защищённые данные. Основная идея заключается в том, что сообщение может включать:

  • исходные данные (content)
  • цифровые подписи
  • сертификаты X.509
  • информацию о шифровании
  • метаданные о алгоритмах

Формат основан на ASN.1 и кодируется чаще всего в DER или PEM представлении. Это обеспечивает совместимость между различными криптографическими библиотеками и системами.

PKCS#7 поддерживает несколько типов структур:

  • SignedData — данные с цифровой подписью
  • EnvelopedData — зашифрованные данные для одного или нескольких получателей
  • SignedAndEnvelopedData — комбинированная структура (устаревшая)
  • DigestedData — данные с хешем
  • EncryptedData — шифрованный контент без структуры получателей

На практике наибольшее распространение получили SignedData и EnvelopedData.

Переход от PKCS#7 к CMS

CMS (RFC 5652) развивает PKCS#7, устраняя его ограничения и уточняя спецификацию. Основные изменения включают:

  • расширенную модульность структуры
  • поддержку новых криптографических алгоритмов
  • более строгую ASN.1 модель
  • улучшенную совместимость с современными стандартами X.509
  • отказ от устаревших конструкций PKCS#7 (например, SignedAndEnvelopedData)

Несмотря на формальное обновление, термин PKCS#7 продолжает использоваться в прикладных системах, особенно в контексте подписи файлов, сертификатов и S/MIME сообщений.

Jsrsasign и поддержка PKCS#7

Библиотека Jsrsasign реализует работу с PKCS#7 и CMS на уровне JavaScript, предоставляя инструменты для создания, анализа и проверки подписанных и зашифрованных структур.

Основные пространства имён, связанные с PKCS#7:

  • KJUR.asn1.cms
  • KJUR.crypto.CMS
  • KJUR.crypto.PKCS7 (в зависимости от версии и сборки)

Библиотека позволяет:

  • формировать SignedData структуры
  • извлекать сертификаты из контейнеров
  • проверять цифровые подписи
  • работать с PEM/DER кодировками
  • обрабатывать вложенные CMS объекты

Формирование SignedData в Jsrsasign

Создание PKCS#7 подписи в Jsrsasign обычно строится вокруг приватного ключа и сертификата X.509.

Типовой процесс включает:

  1. загрузку ключа
  2. загрузку сертификата
  3. формирование подписи
  4. упаковку в PKCS#7 контейнер

Пример структуры данных:

const sig = new KJUR.crypto.Signature({ "alg": "SHA256withRSA" });
sig.init(privateKey);
sig.updateString("Сообщение для подписи");
const signature = sig.sign();

После получения подписи она может быть упакована в PKCS#7 SignedData:

const pkcs7 = new KJUR.asn1.cms.SignedData({
  version: 1,
  hashalgs: ["sha256"],
  content: "Сообщение для подписи",
  certs: [certificate],
  signerinfos: [{
    version: 1,
    id: { type: "isssn", cert: certificate },
    sigalg: "SHA256withRSA",
    signature: signature
  }]
});

const pem = pkcs7.getPEM();

Структура SignedData

SignedData является наиболее важной частью PKCS#7 и CMS. Она включает:

  • версию структуры
  • список алгоритмов хеширования
  • сам контент (или его отсутствие при detached signature)
  • сертификаты подписантов
  • информацию о подписантах
  • сами подписи

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

Detached и attached подписи

PKCS#7 поддерживает два основных режима:

Attached signature

Подпись включает исходные данные внутри контейнера. Такой формат часто используется в архивных системах.

Detached signature

Данные не включаются в PKCS#7 структуру, а передаются отдельно. Это распространено в протоколах, где данные должны оставаться неизменными и независимыми от подписи.

В Jsrsasign режим определяется параметром content или отсутствием вложенного контента.

Проверка PKCS#7 подписи

Процесс верификации включает:

  • извлечение SignedData
  • получение сертификата подписанта
  • проверку цепочки доверия (при необходимости)
  • валидацию криптографической подписи

Пример проверки:

const cms = new KJUR.asn1.cms.SignedData({ pem: pkcs7pem });

const result = cms.verify();

Результат проверки обычно включает информацию о валидности подписи и сертификатов.

Работа с сертификатами внутри PKCS#7

PKCS#7 контейнер может содержать один или несколько сертификатов. Это позволяет передавать всю цепочку доверия вместе с подписью.

Jsrsasign предоставляет методы для:

  • извлечения сертификатов
  • конвертации в PEM формат
  • анализа полей X.509
const certs = cms.getCertificates();

Каждый сертификат представляет собой X.509 структуру с полями:

  • subject
  • issuer
  • serial number
  • public key
  • срок действия

EnvelopedData и шифрование

PKCS#7 EnvelopedData используется для шифрования данных для одного или нескольких получателей.

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

  • генерируется симметричный ключ
  • данные шифруются симметричным алгоритмом
  • ключ шифруется публичным ключом каждого получателя
  • структура упаковывается в PKCS#7 контейнер

Jsrsasign поддерживает создание и разбор таких структур через CMS API.

Пример концептуального использования:

const cms = new KJUR.asn1.cms.EnvelopedData({
  content: "Секретные данные",
  recipients: [{
    cert: recipientCert
  }]
});

const pem = cms.getPEM();

ASN.1 представление PKCS#7

PKCS#7 основан на ASN.1, что определяет строгую иерархию структуры:

  • ContentInfo

    • contentType
    • content (ANY)
  • SignedData

    • version
    • digestAlgorithms
    • contentInfo
    • certificates
    • crls
    • signerInfos

Jsrsasign использует внутренние ASN.1 классы для построения этих структур, скрывая сложность кодирования DER.

Кодировки PEM и DER

PKCS#7 контейнеры могут быть представлены в двух основных форматах:

  • DER (binary)
  • PEM (Base64 с заголовками)

PEM формат в Jsrsasign выглядит следующим образом:

-----BEGIN PKCS7-----
MIIG...
-----END PKCS7-----

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

Взаимодействие PKCS#7 и S/MIME

PKCS#7 широко используется в S/MIME для:

  • подписи email сообщений
  • шифрования писем
  • передачи сертификатов

Jsrsasign позволяет создавать структуры, совместимые с почтовыми клиентами, поддерживающими S/MIME.

Ограничения PKCS#7

Несмотря на широкое распространение, формат имеет ряд ограничений:

  • ограниченная гибкость расширения
  • устаревшие конструкции
  • зависимость от X.509 v1/v3 моделей
  • менее строгая модульность по сравнению с CMS

CMS устраняет эти ограничения, но PKCS#7 продолжает использоваться из-за обратной совместимости.

Практическое значение в Jsrsasign

В JavaScript-экосистеме PKCS#7 через Jsrsasign применяется в задачах:

  • проверка цифровых подписей документов
  • интеграция с PKI инфраструктурой
  • работа с электронными подписями
  • обработка CMS сообщений в браузере и Node.js
  • валидация сертификатов и цепочек доверия

Jsrsasign предоставляет высокоуровневый интерфейс, скрывающий ASN.1 сложность и позволяющий работать с криптографическими структурами на уровне объектов JavaScript.