Кодирование подписанных данных
Подписанные данные состоят из содержимого любого типа и зашифрованных хэшей сообщений содержимого, равного нулю или нескольким подписателям. Полученный хэш может подтвердить, что исходное сообщение не было изменено с момента подписания и что определенные лица или организации подписали данные.
На следующем рисунке показана процедура кодирования подписанного сообщения. Эти шаги описаны в списке, приведенном ниже.
Сообщение может содержать несколько подписывателей, алгоритмов хэширования и сертификатов. Хотя на рисунке показаны только сертификаты, списки отзыва сертификатов и списки сертификатов могут использовать один и тот же процесс. Они будут вписываться в иллюстрацию, где бы ни отображались сертификаты.
Общий процесс кодирования подписанных данных выглядит следующим образом.
Кодирование подписанных данных
- Создаются данные (при необходимости) и извлекается указатель на него.
- Откроется хранилище сертификатов , содержащее сертификат подписывателя.
- Извлекается закрытый ключ для сертификата. Перед использованием сертификата необходимо задать два свойства. Один из них используется для привязки сертификата к определенному поставщику служб конфигурации, а в рамках этого CSP — к конкретному контейнеру закрытого ключа. Другой используется для указания того, какой алгоритм хэширования следует использовать при вызове хэш-операции . Их необходимо задать только один раз.
- Свойство сертификата определяет хэш-алгоритм.
- Хэш данных создается путем отправки данных через функцию хэширования.
- Подпись создается путем шифрования хэша с помощью закрытого ключа, полученного через свойство сертификата.
- В готовое подписанное сообщение включаются следующие данные:
- Исходные данные для подписи
- Хэш-алгоритмы
- Подписи
- Структуры сведений о подписывшем, включая идентификатор подписывателя (издатель сертификата и серийный номер).
- Сертификаты подписывателя (необязательно)
Эта процедура иллюстрирует простой случай. Более сложные случаи включают в себя атрибуты, прошедшие проверку подлинности, включенные в сообщение. Если тип контента не является строкой BYTE или имеется по крайней мере один атрибут, прошедший проверку подлинности вместе с любым типом данных, требуются два стандартных атрибута: тип содержимого (данных) и хэш содержимого. В таких случаях CryptoAPI автоматически предоставляет эти два обязательных атрибута. Низкоуровневые функции сообщений хэшируют атрибуты, прошедшие проверку подлинности, шифруют хэш с помощью закрытого ключа и предоставляют его в качестве подписи.
Используйте низкоуровневые функции сообщений для выполнения только что перечисленных задач с помощью следующей процедуры.
Кодирование подписанного сообщения
Создайте или получите содержимое.
Получение поставщика служб шифрования.
Получение сертификатов подписывателя.
Инициализируйте структуру CMSG_SIGNER_ENCODE_INFO .
Инициализируйте структуру CMSG_SIGNED_ENCODE_INFO .
Вызовите CryptMsgCalculateEncodedLength , чтобы получить размер большого двоичного объекта закодированного сообщения. Выделите для него память.
Вызовите CryptMsgOpenToEncode, передав CMSG_SIGNED для dwMsgType и указатель на CMSG_SIGNED_ENCODE_INFO для pvMsgEncodeInfo , чтобы получить дескриптор открытого сообщения.
Вызовите CryptMsgUpdate, передав дескриптор, полученный на шаге 7, и указатель на данные, которые должны быть подписаны и закодированы. Эту функцию можно вызывать столько раз, сколько необходимо для завершения процесса кодирования.
Вызовите CryptMsgGetParam, передав дескриптор, полученный на шаге 7, и соответствующие типы параметров для доступа к нужным закодированным данным. Например, передайте CMSG_CONTENT_PARAM, чтобы получить указатель на все сообщение PKCS 7 .
Если результат этой кодировки будет использоваться в качестве внутренних данных для другого закодированного сообщения, например конвертированного сообщения, необходимо передать параметр CMSG_BARE_CONTENT_PARAM. Пример, демонстрирующий это, см. в разделе Альтернативный код для кодирования конвертированного сообщения.
Закройте сообщение, вызвав CryptMsgClose.
Результатом этой процедуры является закодированное сообщение, содержащее исходные данные, зашифрованный хэш этих данных (подпись) и сведения о подписывшем. Также имеется указатель на нужный закодированный большой двоичный объект.
Сведения о кодировании на языке C см. в разделе Пример программы C: подписывание, кодирование, декодирование и проверка сообщения.