При работе с электронным документооборотом программисты 1С часто сталкиваются с задачей подписания XML-файлов. Одной из самых запутанных тем является выбор способа «присоединения» подписи. Часто возникает путаница: нужно ли вставлять подпись внутрь структуры XML (стандарт XMLDSig) или создать единый бинарный файл, содержащий и подпись, и исходные данные (присоединенная подпись PKCS#7). Для регулярной передачи таких файлов программа для обмена данными по расписанию настраивается поверх существующего плана обмена без изменения самих конфигураций.
В этой статье мы подробно разберем, как реализовать оба варианта, проанализируем типичные ошибки и выясним, какие методы платформы и Библиотеки стандартных подсистем (БСП) лучше использовать в разных ситуациях. Для поиска расхождений в данных после доработки механизмов обмена программа автоматической сверки баз 1С подключается к проверяемым объектам через COM-соединение.
Прежде чем переходить к коду, давайте разберем теорию. Существует два основных способа формирования подписи в формате CMS/PKCS#7:
.p7s или .sig), который содержит только криптографический отпечаток. Оригинальный XML-файл при этом остается неизменным. Для проверки такой подписи нужны оба файла.Многие внешние системы (например, государственные порталы или КриптоАРМ) под «присоединением подписи» понимают именно второй вариант — создание единого бинарного контейнера. В случаях, когда прямая интеграция с ними затруднена, платформа для создания программных роботов выполняет действия в интерфейсе внешних программ без API для обмена данными.
Если вам нужно получить присоединенную подпись в формате PKCS#7 (как это делает КриптоАРМ), проще всего использовать встроенный объект платформы МенеджерКриптографии. Рассмотрим, как это сделать правильно.
Ошибка многих разработчиков заключается в игнорировании четвертого параметра метода Подписать(). Посмотрите на следующий пример кода:
// Инициализируем менеджер криптографии
// Параметры: имя криптопровайдера, путь к модулю (обычно пустые для CryptoPro), тип (80 для ГОСТ 2012)
МенеджерКриптографии = Новый МенеджерКриптографии("", "", 80);
// Устанавливаем пароль к закрытому ключу сертификата
МенеджерКриптографии.ПарольДоступаКЗакрытомуКлючу = "ВашПароль";
// Файлы
ФайлЗапроса = "C:\Temp\запрос.xml";
ФайлРезультата = "C:\Temp\запрос.xml.p7s";
// ВАЖНО: Четвертый параметр 'ТолькоПодпись'
// Ложь — создается присоединенная подпись (данные внутри)
// Истина — создается отсоединенная подпись (только подпись)
МенеджерКриптографии.Подписать(ФайлЗапроса, ФайлРезультата, Сертификат, Ложь);
Если вы установите четвертый параметр в значение Ложь, платформа упакует ваш XML внутрь .p7s. Это и будет тот самый «файл с подписью в начале», который часто требуют информационные системы. Проанализируем результат: теперь ФайлРезультата — это самодостаточный объект, который можно отправить получателю без исходного XML. Для быстрой реализации такого механизма можно воспользоваться обработкой для подписания файлов средствами платформы 1С.
Если в вашей конфигурации внедрена БСП (модуль ЭлектроннаяПодпись), рекомендуется использовать её функции. Это обеспечит корректную работу с хранилищами сертификатов и логирование операций.
Для серверного (синхронного) подписания данных, чтобы получить присоединенную подпись, используем следующий алгоритм:
// Подготовка данных
ДанныеДляПодписи = Новый ДвоичныеДанные("C:\Temp\запрос.xml");
// Параметры подписания
ПараметрыПодписи = ЭлектроннаяПодпись.ПараметрыПодписи();
ПараметрыПодписи.Сертификат = ВыбранныйСертификат;
// Метод Подписать на сервере возвращает ДвоичныеДанные готового контейнера
// По умолчанию БСП формирует отсоединенную подпись.
// Чтобы включить данные в подпись, нужно настроить параметры расширения или использовать низкоуровневые методы.
РезультатПодписания = ЭлектроннаяПодпись.Подписать(ДанныеДляПодписи, ПараметрыПодписи);
// Запись результата в файл
РезультатПодписания.Записать("C:\Temp\запрос_с_подписью.sig");
Обратите внимание, что в современных версиях БСП клиентские методы (ЭлектроннаяПодписьКлиент.Подписать) являются асинхронными. Они возвращают результат через ОписаниеОповещения. Если вам нужно встроить подписание в существующий линейный код, всегда выполняйте подписание на стороне сервера.
Иногда под «присоединением подписи к XML» понимают стандарт XMLDSig (Enveloped). В этом случае подпись в формате XML вставляется непосредственно в структуру самого документа в виде тега <Signature>. Это принципиально отличается от бинарного контейнера PKCS#7.
Для реализации XMLDSig через БСП часто используют следующий подход (разберем пример, который часто вызывает ошибки):
ПараметрыКонверта = ЭлектроннаяПодписьКлиент.ПараметрыКонвертаXML();
ПараметрыКонверта.СообщениеXML = ТекстВашегоXML; // Передаем содержимое файла
ОписаниеДанных = Новый Структура;
ОписаниеДанных.Вставить("Операция", "ПодписаниеДанных");
ОписаниеДанных.Вставить("Данные", ЭлектроннаяПодписьКлиент.КонвертXML(ПараметрыКонверта));
// Вызов асинхронного метода
ЭлектроннаяПодписьКлиент.Подписать(ОписаниеДанных, Неопределено, ОбработкаРезультата);
Важное предостережение: Если при использовании этого метода вы получаете ошибку Поле объекта не обнаружено (КонвертSOAP), это означает, что программный интерфейс БСП ожидает структуру для работы с веб-сервисами (SOAP), а вы передали обычные данные. Проверьте, заполнены ли свойства структуры ПараметрыКонвертаXML и соответствует ли ваш XML требованиям схемы DSIG.
Рассмотрим основные причины, по которым подпись может «не подходить» принимающей стороне:
ЗаписьТекста с явным указанием кодировки без BOM.80.Клиент). Используйте только серверные методы МенеджерКриптографии или ЭлектроннаяПодпись, так как они работают в синхронном режиме и не требуют взаимодействия с пользователем.Подводя итог, выясним: если вам нужно просто «склеить» файл и подпись в один файл (как в КриптоАРМ), используйте МенеджерКриптографии.Подписать(..., Ложь). Если же ваша задача — интеграция с государственными ИС через API, скорее всего, вам потребуется стандарт XMLDSig, который лучше реализовывать через специализированные методы БСП или внешние компоненты (например, КриптоПро ЭЦП Browser plug-in).