Как подписать текстовый файл присоединенной электронной подписью (ЭЦП) в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с электронным документооборотом в 1С часто возникает задача подписания файлов электронной подписью. Одной из специфических и порой сложных требований является создание присоединенной электронной подписи, когда сама подпись находится непосредственно внутри подписанного файла, а не в отдельном файле (отсоединенная подпись). В этой статье мы подробно рассмотрим, как решить эту задачу в контексте 1С, анализируя ограничения встроенных средств и предлагая альтернативные решения.

Основная проблема, с которой мы сталкиваемся, заключается в том, что стандартные механизмы 1С для подписания файлов, особенно текстовых (TXT), преимущественно ориентированы на создание отсоединенной подписи. Отсоединенная подпись представляет собой отдельный файл, который содержит только саму подпись и ссылку на исходные данные, которые она подтверждает. Принимающая же сторона в некоторых случаях требует, чтобы и данные, и подпись были в одном файле, что чаще всего подразумевает формат PKCS#7 (CMS).

Почему стандартные средства 1С не подходят для присоединенной подписи текстовых файлов

Начнем с анализа встроенных возможностей 1С. Если мы попытаемся использовать стандартный объект МенеджерКриптографии для подписания файла, то увидим, что он по умолчанию создает отсоединенную подпись.

Рассмотрим пример кода, демонстрирующий такое поведение:


ТипМенеджераКриптографии = 81; 
МенеджерКриптографии = Новый МенеджерКриптографии("", "", ТипМенеджераКриптографии); 
// ...
МенеджерКриптографии.ВключениеСертификатовВПодпись = РежимВключенияСертификатовКриптографии.НеВключать; 
МенеджерКриптографии.Подписать(ФайлЗапроса, ФайлЗапроса + ".p7s", Сертификат);

В этом примере МенеджерКриптографии.Подписать(ФайлЗапроса, ФайлЗапроса + ".p7s", Сертификат) создаст файл подписи с расширением .p7s (или аналогичным), который будет находиться отдельно от исходного ФайлЗапроса. Это и есть отсоединенная подпись.

Почему же 1С так поступает? Причина кроется в особенностях формата TXT. Обычный текстовый файл не имеет встроенной структуры для хранения метаданных, таких как цифровая подпись, без изменения его исходного содержимого. Если мы просто добавим подпись в конец текстового файла, это изменит сам текст, и подпись станет недействительной. В отличие от TXT, формат PDF, например, поддерживает присоединенную подпись, потому что цифровая подпись вставляется в отдельный слой документа, не затрагивая его основное содержимое. Это позволяет даже многократно подписывать документ, сохраняя валидность всех подписей.

Как отмечается в документации к Библиотеке стандартных подсистем (БСП) 1С, "В программе 1С:Предприятие возможна работа только с отсоединенной электронной подписью. Работа с присоединенными подписями и подписями внутри документа в программе недоступна." Это подтверждает, что встроенные средства 1С не предназначены для создания присоединенных подписей для большинства форматов документов, за исключением некоторых специфических случаев, таких как PDF.

Попытка использования COM-объекта CAdESCOM

Один из возможных путей решения проблемы — использование внешних криптографических компонент, доступных через COM-объекты. Платформа 1С позволяет работать с такими объектами, и библиотека CAdESCOM, входящая в состав КриптоПро CSP, является мощным инструментом для работы с цифровыми подписями.

Мы можем попытаться создать присоединенную подпись с помощью CAdESCOM.CadesSignedData. Рассмотрим пример такого кода:


oSignedData = Новый COMОбъект("CAdESCOM.CadesSignedData");
oSignedData.Content = Base64Строка(ДвоичныеДанные); 
oSignedMessage = oSignedData.SignCades(oCertificate, 65535, false, 0);

В этом коде мы создаем объект CAdESCOM.CadesSignedData, передаем ему содержимое файла в кодировке Base64 через свойство Content, а затем пытаемся подписать его методом SignCades, используя сертификат oCertificate и определенные параметры.

Однако при выполнении этого кода мы можем столкнуться с ошибкой: CAdESCOM.CadesSignedData.1 Интерфейс не поддерживается. Это довольно распространенная ошибка, которая может указывать на несколько причин:

  1. Версия CAdESCOM: Возможно, установленная версия компоненты CAdESCOM устарела и не содержит необходимого функционала для выбранного типа подписи или режима работы. Некоторые режимы или типы подписей могли быть добавлены в более поздних версиях библиотеки.
  2. Неправильные параметры: Неверные значения, переданные в метод SignCades (например, 65535, false, 0), могут быть интерпретированы компонентой как запрос неподдерживаемого интерфейса или типа подписи. Важно тщательно свериться с документацией CAdESCOM для корректных значений флагов и типов подписей для присоединенной подписи PKCS#7 (CMS).
  3. Отсутствие необходимых сертификатов/контейнеров: Хотя это напрямую не вызывает ошибку "интерфейс не поддерживается", некорректная настройка криптопровайдера, отсутствие доступа к закрытому ключу сертификата или другие проблемы с криптографическим окружением могут косвенно влиять на успешность операции подписания.

Если нам удастся корректно использовать CAdESCOM для создания присоединенной подписи, результатом будет один бинарный файл. При просмотре такого файла в обычном текстовом редакторе он будет выглядеть как набор нечитаемых символов ("иероглифов"), поскольку он содержит бинарные данные подписи вместе с исходным текстом. Именно такой формат, скорее всего, ожидает принимающая сторона, если она использует "КриптоАРМ со снятой галочкой 'сохранить подпись в отдельном файле'".

Использование внешних утилит: csptest.exe и КриптоАРМ

Учитывая ограничения 1С и сложности с CAdESCOM, наиболее надежным и проверенным решением является использование внешних консольных утилит или программ, которые специально предназначены для работы с криптографией.

Применение утилиты csptest.exe

Утилита csptest.exe является частью комплекта КриптоПро CSP и предоставляет широкие возможности для работы с криптографическими операциями из командной строки. С ее помощью мы можем создать присоединенную подпись в формате PKCS#7 (CMS).

Рассмотрим пример команды для подписания файла, который создает присоединенную подпись:


rem Подписать файл присоединенной ЭЦП
csptest -sfsign -sign -in 08_110400716550_002_19012023_B6662EA1-EC95-423A-95B5-793526329DA9.xml -out 08_110400716550_002_19012023_B6662EA1-EC95-423A-95B5-793526329DA9.xml.sig -my B030C18CB16B8A0EFBDB7DB5F8131D5C2E2617D1 -addsigtime -add

Разберем параметры этой команды:

  1. csptest: Вызов самой утилиты.
  2. -sfsign: Указывает на выполнение операции с подписью (Signature File operations).
  3. -sign: Обозначает, что мы хотим подписать файл.
  4. -in <исходный_файл>: Путь к исходному файлу, который необходимо подписать (в примере это 08_110400716550_002_19012023_B6662EA1-EC95-423A-95B5-793526329DA9.xml, но это может быть любой текстовый файл).
  5. -out <выходной_файл_с_подписью>: Путь и имя для выходного файла, который будет содержать присоединенную подпись (в примере это 08_110400716550_002_19012023_B6662EA1-EC95-423A-95B5-793526329DA9.xml.sig). Отсутствие флага -detached или -nostore гарантирует создание присоединенной подписи, то есть данные будут включены в выходной файл.
  6. -my <отпечаток_сертификата>: Отпечаток (хеш) сертификата, которым будет осуществляться подписание. Это позволяет программе найти нужный сертификат в хранилище пользователя.
  7. -addsigtime: Добавляет в подпись атрибут "время подписи".
  8. -add: Добавляет информацию о подписи.

Результатом выполнения этой команды будет файл 08_110400716550_002_19012023_B6662EA1-EC95-423A-95B5-793526329DA9.xml.sig, который будет содержать как исходные данные, так и саму подпись в одном бинарном блоке. Этот файл является присоединенной подписью в формате PKCS#7 (CMS) и будет соответствовать требованиям принимающей стороны, ожидающей "КриптоАРМ подписано со снятой галочкой 'сохранить подпись в отдельном файле'".

Для вызова этой утилиты из 1С мы можем использовать объект ЗапуститьПриложение или WShell.Run, передавая ей сформированную командную строку.


&НаКлиенте
Процедура ПодписатьФайлЧерезCsptest()
    // Предполагается, что файл уже сохранен на диск
    ПутьКИсходномуФайлу = "C:\МоиДокументы\текстовый_файл.txt";
    ПутьКПодписанномуФайлу = "C:\МоиДокументы\текстовый_файл.txt.sig";
    ОтпечатокСертификата = "B030C18CB16B8A0EFBDB7DB5F8131D5C2E2617D1"; // Замените на реальный отпечаток

    КомандаCsptest = "csptest -sfsign -sign -in " + """""" + ПутьКИсходномуФайлу + """""" + 
                    " -out " + """""" + ПутьКПодписанномуФайлу + """""" + 
                    " -my " + ОтпечатокСертификата + " -addsigtime -add";

    // Для запуска на клиенте
    WShell = Новый COMОбъект("WScript.Shell");
    WShell.Run(КомандаCsptest, 0, Истина); // 0 - скрыть окно, Истина - дождаться завершения
    
    Сообщить("Файл успешно подписан и сохранен как: " + ПутьКПодписанномуФайлу);
Исключение
    Сообщить("Ошибка при подписании файла: " + ОписаниеОшибки());
КонецПроцедуры

Важно: Утилита csptest.exe должна быть доступна в системном PATH или по полному пути. Также необходимо, чтобы на компьютере был установлен КриптоПро CSP и соответствующий сертификат для подписания.

Использование КриптоАРМ

Как упоминалось в обсуждении, программа КриптоАРМ также умеет создавать присоединенные подписи. При выборе опции "Присоединенная электронная подпись" и снятии галочки "сохранить подпись в отдельном файле", КриптоАРМ фактически создает криптографический контейнер (часто с расширением .p7m или .sgn), который содержит исходный файл и его цифровую подпись. Этот контейнер также является бинарным файлом.

Если требуется автоматизация процессов подписания через КриптоАРМ из 1С, то можно рассмотреть два пути:

  1. Командная строка КриптоАРМ: КриптоАРМ имеет интерфейс командной строки, аналогичный csptest.exe, который позволяет вызывать его функции подписания с определенными параметрами. Для получения информации о доступных параметрах следует обратиться к документации КриптоАРМ.
  2. API КриптоАРМ: Если КриптоАРМ предоставляет COM-объекты или другие программные интерфейсы (API), то можно попробовать взаимодействовать с ними напрямую из 1С. Однако это потребует более глубокого изучения документации КриптоАРМ и может быть сложнее в реализации, чем использование консольных утилит. Если у стороннего приложения отсутствует программный интерфейс для интеграции, то для автоматизации повторяющихся действий в его графической оболочке можно задействовать платформу роботизации пользовательских сценариев One RPA.

Форматы присоединенных подписей и их особенности

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

PKCS#7 (CMS)

PKCS#7 (Cryptographic Message Syntax - CMS) является наиболее распространенным стандартом для криптографических сообщений. Он позволяет создавать как отсоединенные, так и присоединенные подписи. Когда мы говорим о присоединенной подписи в формате PKCS#7 (часто такие файлы имеют расширение .p7m, .sgn или просто .sig без указания "отсоединенности"), мы имеем в виду единый бинарный блок, который содержит:

Именно такой формат, вероятнее всего, ожидается принимающей стороной, если она упоминает "КриптоАРМ со снятой галочкой 'сохранить подпись в отдельном файле'". При попытке открыть такой файл в обычном текстовом редакторе мы увидим набор "иероглифов" или нечитаемых символов, поскольку это бинарный контейнер, а не чистый текст.

XMLDSig

В ходе обсуждения также упоминался XMLDSig (XML Digital Signature). Это стандарт для электронной подписи, предназначенный специально для XML-документов. В этом случае подпись встраивается непосредственно в XML-структуру документа, обычно в виде нового элемента <Signature>. XMLDSig очень гибок и позволяет подписывать как весь XML-документ целиком, так и его отдельные части (элементы, атрибуты).

Однако, как было справедливо отмечено в обсуждении, XMLDSig не подходит для нашей задачи по нескольким причинам:

  1. Исходный файл является обычным текстовым файлом (TXT), а не XML. Чтобы использовать XMLDSig, нам пришлось бы сначала преобразовать текстовый файл в XML-формат (например, заключив его содержимое в CDATA блок внутри XML-тега).
  2. Принимающая сторона ожидает не XML-файл с подписью, а бинарный контейнер PKCS#7 с исходным текстовым содержимым и подписью. Преобразование в XML-формат, скорее всего, не будет принято.

Таким образом, хотя XMLDSig является мощным инструментом для подписания XML-документов, он не является решением для создания присоединенной подписи к простому текстовому файлу, когда принимающая сторона не поддерживает формат XML.

Заключение

Подводя итог, мы выяснили, что создание присоединенной электронной подписи для текстовых файлов напрямую средствами 1С затруднено и часто невозможно из-за архитектурных особенностей формата TXT и ограничений встроенного функционала платформы.

Для успешного решения задачи, когда принимающая сторона ожидает единый файл, содержащий и текст, и подпись (формат PKCS#7/CMS), мы рекомендуем сосредоточиться на следующих подходах:

  1. Использование внешних консольных утилит: Самым надежным и простым в реализации является вызов утилиты csptest.exe из состава КриптоПро CSP через командную строку 1С. Эта утилита позволяет создать присоединенную подпись в требуемом формате.
  2. Использование COM-объектов CAdESCOM: При правильной настройке и корректном использовании, библиотека CAdESCOM также может создавать присоединенные подписи. Однако это может потребовать более глубокого изучения ее документации и отладки параметров для избежания ошибок типа "Интерфейс не поддерживается".
  3. Использование КриптоАРМ: Если КриптоАРМ уже используется принимающей стороной, то можно рассмотреть использование его командной строки или API для автоматизации процесса подписания.

В любом из этих случаев, результирующий файл будет бинарным контейнером, который визуально не будет похож на исходный текстовый файл, но будет содержать его и цифровую подпись, что и является целью создания присоединенной ЭЦП.

← На главную