Поиск по блогу

суббота, 27 августа 2016 г.

Создание ЭП-ОВ для взаимодействия со СМЭВ

Проверка подписи XMLDSIG (WS-Security) с помощью сервиса СПЭП СМЭВ
Проверка подписи XMLDSIG на примере СМЭВ

Для взаимодействия со СМЭВ, все исходящие сообщения информационной системы, подключенной к СМЭВ, должны быть подписаны с целью удостоверения данных. Требования к алгоритмам создания электронной подписи информационной системы следующие:
  • алгоритмы для расчета хеш-сумм - ГОСТ Р 34.11-94;
  • формирования подписи - ГОСТ Р 34.10-2001.
Сообщение СМЭВ представляет собой XML документ, который подписывается ЭП по формату XMLDSIG (спецификация WS-Security). Подробное описание алгоритма создания ЭП находится в методических рекомендациях СМЭВ. Алгоритм можно реализовать самостоятельно, но в данной статье создание ЭП будем выполнять с помощью программных продуктов компании КриптоПро.

Первым делом выполняем установку продуктов КриптоПро CSP и КриптоПро CADESCOM. К сожалению они являются платными, но использовать триальную версию можно 90 дней. Если подпись будет создаваться на клиенте (&НаКлиенте), то устанавливаем на клиентскую машину КриптоПро. Если же создание подписи будет происходит на сервере (&НаСервере), то соответственно устанавливаем КриптоПро на тот компьютер, где установлен сервер 1С:Предприятие.

После установки продуктов КриптоПро, устанавливаем сертификат электронной подписи с привязкой к закрытому ключу в хранилище сертификатов на тот компьютер, где будет выполняться создание ЭП (см. рисунок 1). Хранилище сертификатов делится два типа: хранилище пользователя и локального компьютера. Если создание подписи будет выполнять сервер, то рекомендуется установить сертификат в хранилище локального компьютера, так как в этом случае всем пользователям системы будет доступен сертификат. Если же вы точно знаете от имени какого пользователя будет происходит создание подписи, то можно установить сертификат в хранилище пользователя (например, USR1CV82).
Рисунок 1. Личные сертификаты текущего пользователя
Создание подписи на платформе 1С выполняется с помощью COM-объектов, которые регистрируются в процессе установки КриптоПро CADESCOM. Сам XML документ перед созданием подписи подготавливается соответствующим образом. В заголовок XML документа вставляется структура Security по спецификации WS-Security с сертификатом ЭП, в формате Base64. Описание создания структуры Security в заголовке находится в статье Подготовка SOAP-сообщения перед созданием подписи XMLDSIG на примере СМЭВ, сертификат в формате Base64 помещается в структуру в момент создания подписи.
ИC органа власти (потребителя) при формировании запроса к ИС поставщика, а также ИС поставщика при формировании ответа должны проставлять в атрибуте actor значение, соответствующее СМЭВ как стороне проверяющей подпись:

soapenv:actor="http://smev.gosuslugi.ru/actors/smev"

Алгоритм:


1. Находим установленный сертификат в хранилище сертификатов. Поиск осуществляется с помощью COM-объекта CAPICOM.Store по отпечатку, можно и по другим свойствам искать сертификат, но для однозначной идентификации лучше по отпечатку.

Store = Новый COMОбъект("CAPICOM.Store");
Store.Open(CAPICOM_CURRENT_USER_STORE, CAPICOM_MY_STORE, CAPICOM_STORE_OPEN_READ_ONLY);
Отпечаток = СтрЗаменить(Строка(Base64Значение(ОтпечатокBase64)), " ", "");
Certificates = Store.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH, Отпечаток);
Сертификат = Certificates.Item(1);


Константой CAPICOM_CURRENT_USER_STORE мы указываем, что нужно искать сертификат в ветке Личное (см. рисунок 1). Константой CAPICOM_MY_STORE указываем, что ветку Личное берем из хранилища пользователя. Подробное описание параметров метода Open() смотрите на MSDN.

Так же поиск сертификатов можно выполнять и объектом МенеджерКриптографии платформы 1С.

МенеджерКриптографии = Новый МенеджерКриптографии("Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider", "", 75);
ХранилищеСертификатов = МенеджерКриптографии.ПолучитьХранилищеСертификатов(
    ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты,
    РасположениеХранилищаСертификатовКриптографии.ДанныеПользователяОС);
Сертификат = ХранилищеСертификатов.НайтиПоОтпечатку(Base64Значение(ОтпечатокBase64));


В рамках поставленной задачи поиск сертификата объектом МенеджерКриптографии не подходит.

2. Создаем COM-объект CAdESCOM.CPSigner, для которого указываем найденный сертификат и секретный ключ. Секретный ключ - это пароль, установленный на контейнер закрытого ключа, запрашивается при каждом обращении к нему.

CPSigner = Новый COMОбъект("CAdESCOM.CPSigner");
CPSigner.Certificate = Сертификат;
CPSigner.KeyPin = СекретныйКлюч;


3. Вставляем в подготовленный XML документ найденный сертификат в формате Base64 и передаем его в свойство Content COM-объекта CAdESCOM.SignedXML с указанием типа подписи в свойстве SignatureType - в данном случае по шаблону XML документа. Создаем подпись, вызвав метод Sign(), параметром которого будет COM-объект CAdESCOM.CPSigner.

СтрокаXML = СтрЗаменить(СтрокаXML, "#Certificate_ENCODE_BASE64", Сертификат.Export(CADESCOM_ENCODE_BASE64));
SignedXML = Новый COMОбъект("CAdESCOM.SignedXML");
SignedXML.Content = СтрокаXML;
SignedXML.SignatureType = CADESCOM_XML_SIGNATURE_TYPE_TEMPLATE;
ПодписаннаяXMLСтрока = SignedXML.Sign(CPSigner)


Итоговый программный код:


// Константы.
CADESCOM_XML_SIGNATURE_TYPE_TEMPLATE = 2;
CAPICOM_CERTIFICATE_FIND_SHA1_HASH = 0;
CAPICOM_LOCAL_MACHINE_STORE = 1;
CAPICOM_CURRENT_USER_STORE = 2;
CAPICOM_MY_STORE = "My";
CAPICOM_STORE_OPEN_READ_ONLY = 0;
CAPICOM_STORE_OPEN_READ_WRITE = 1;
CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED = 2;
CADESCOM_ENCODE_BASE64 = 0;
// Информация о сертификате.
ОтпечатокBase64 = "jkGzVXJWs5NB4mRsHLtlcWrcyvg=";
СекретныйКлюч = "12345678";
// Поиск сертификата.
Store = Новый COMОбъект("CAPICOM.Store");
Store.Open(CAPICOM_CURRENT_USER_STORE, CAPICOM_MY_STORE, CAPICOM_STORE_OPEN_READ_ONLY);
Отпечаток = СтрЗаменить(Строка(Base64Значение(ОтпечатокBase64)), " ", "");
Certificates = Store.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH, Отпечаток);
Сертификат = Certificates.Item(1);
// Создание подписи.
CPSigner = Новый COMОбъект("CAdESCOM.CPSigner");
CPSigner.Certificate = Сертификат;
CPSigner.KeyPin = СекретныйКлюч;

// СтрокаXML - это подготовленный XML документ, в который
// вставляется сертификат в формате base64
СтрокаXML = СтрЗаменить(СтрокаXML, "#Certificate_ENCODE_BASE64", Сертификат.Export(CADESCOM_ENCODE_BASE64));
SignedXML = Новый COMОбъект("CAdESCOM.SignedXML");
SignedXML.Content = СтрокаXML;
SignedXML.SignatureType = CADESCOM_XML_SIGNATURE_TYPE_TEMPLATE;
ПодписаннаяСтрокаXML = SignedXML.Sign(CPSigner);


Материал статьи основан на примере создания и проверки подписи документа XML по шаблону, который размещен в руководстве разработчика КриптоПро.

Создание электронной подписи может завершиться ошибкой неприятной ошибкой
"Неправильный параметр набора ключей", один из вариантов решения такой ошибки приведен в статье Неправильный параметр набора ключей при создании ЭП на стороне сервера.

Скачать пример обработки можно по этой ссылке.

4 комментария:

  1. Добрый день! Пытаюсь повторить ваш пример, установил Cadescom и capicom, создал объект CAdESCOM.CPSigner, однако у него нет такого свойства CPSigner.KeyPin и соответственно при попытке его определить мне выходит ошибка. В чем может быть дело?

    ОтветитьУдалить
  2. Разобрался сам, оказалось что я установил плагин ,но этого было недостаточно. Установил КриптоПро ЭЦП SDK и все нормально заработало

    ОтветитьУдалить
    Ответы
    1. Для работы данного кода достаточно установить КриптоПро CSP и КриптоПро CADESCOM. Вероятнее всего, что вы делали что-то не так.

      Удалить
    2. Вставлю свои пять копеек. Если установить КриптоПро CSP и КриптоПро CADESCOM, то компонента CAPICOM установлена не будет. Это можно проверить в реестре.
      Компонента CAPICOM может быть установлена при установке КриптоПро ЭЦП SDK, о чём написано на сайте КриптоПро.

      С уважением, Станислав

      Удалить