В процессе интеграции систем электронного документооборота часто возникает задача формирования подписи, строго соответствующей формату CMS SignedData в бинарной DER-кодировке. При работе в среде 1С:Предприятие для этих целей традиционно используются инструменты КриптоПро. Однако разработчики часто сталкиваются как с инфраструктурными ошибками (невозможность создания COM-объектов), так и с логическими нюансами настройки параметров криптографии.
В этой статье мы совместно разберем процесс настройки сервера, проанализируем причины возникновения ошибок и шаг за шагом напишем программный код для генерации корректной электронной подписи.
Одной из самых распространенных проблем при начале работы с КриптоПро в 1С является ошибка -2147221005 (0x800401f3): Ошибка при вызове конструктора (COMОбъект): Недопустимая строка с указанием класса. Эта ошибка означает, что операционная система не может найти в реестре сведения о запрашиваемом программном идентификаторе (ProgID), таком как CAdESCOM.CadesSignedData. При необходимости выполнять криптографические операции без вызова COM-объектов можно использовать набор обработок с алгоритмами шифрования на чистом 1С.
Проанализируем ситуацию: простого наличия установленного КриптоПро CSP на сервере недостаточно. Для работы через программные интерфейсы в 1С необходимо наличие компоненты КриптоПро ЭЦП Browser plug-in (несмотря на название "Browser", она предоставляет необходимые COM-интерфейсы для серверных приложений).
Разберем шаги по устранению этой проблемы:
CAdESCOM.Store, CAdESCOM.CPSigner и других.regsvr32.Для формирования подписи нам потребуется три основных объекта. Давайте рассмотрим их назначение:
CAdESCOM.Store — хранилище сертификатов (позволяет найти нужный сертификат в личном хранилище пользователя).CAdESCOM.CPSigner — объект, представляющий "подписанта". Здесь мы указываем сертификат и дополнительные опции подписи.CAdESCOM.CadesSignedData — основной объект для работы с данными, который выполняет операцию подписания.Рассмотрим пример кода для инициализации хранилища и поиска сертификата по его отпечатку (Thumbprint):
// Инициализируем хранилище
Попытка
Store = Новый COMОбъект("CAdESCOM.Store");
// Открываем личное хранилище текущего пользователя только для чтения
// 2 - CAPICOM_CURRENT_USER_STORE, "My" - личные сертификаты
Store.Open(2, "My", 0);
Исключение
Сообщить("Ошибка открытия хранилища: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Поиск сертификата по отпечатку
Сертификат = Неопределено;
Для Каждого ТекущийСертификат Из Store.Certificates Цикл
Если СокрЛП(ТекущийСертификат.Thumbprint) = ОтпечатокСтрока Тогда
Сертификат = ТекущийСертификат;
Прервать;
КонецЕсли;
КонецЦикла;
Store.Close();
Если Сертификат = Неопределено Тогда
Сообщить("Сертификат с указанным отпечатком не найден!");
Возврат;
КонецЕсли;
Когда сертификат найден, необходимо настроить объект CPSigner. Важно обратить внимание на свойство Options. Значение 2 (CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY) означает, что в подпись будет включен только сам сертификат подписанта, без всей цепочки доверия. Это часто требуется для экономии места и соответствия специфическим требованиям информационных систем.
Проанализируем настройку кодировки контента. Это критический момент: если вы подписываете бинарные данные (например, PDF или XML), необходимо правильно указать способ передачи этих данных в объект. Рассмотрим следующий фрагмент:
Signer = Новый COMОбъект("CAdESCOM.CPSigner");
Signer.Certificate = Сертификат;
Signer.Options = 2; // Включаем только сертификат автора
CadesSignedData = Новый COMОбъект("CAdESCOM.CadesSignedData");
// Установка кодировки контента
// 1 - CADESCOM_ENCODE_BINARY (данные передаются в формате Base64)
// 0 - CADESCOM_ENCODE_BASE64 (данные передаются как обычная строка)
CadesSignedData.ContentEncoding = 1;
CadesSignedData.Content = Base64Строка(ДвоичныеДанныеФайла);
Важное замечание: Если вы устанавливаете ContentEncoding = 1, объект CadesSignedData ожидает, что в свойство Content будет передана строка Base64. Это позволяет корректно обрабатывать бинарные файлы без потери данных из-за проблем с кодировками текста.
Для получения формата CMS SignedData (стандарт PKCS#7) лучше всего подходит метод SignCades с типом 1 (CADESCOM_CADES_BES). Формат CAdES-BES является надмножеством CMS, и большинство современных систем принимают его. Если же требуется строго "чистый" CMS без атрибутов CAdES, используется метод Sign.
По умолчанию методы возвращают подпись в виде строки Base64. Чтобы получить DER-кодировку (бинарный вид), нам нужно преобразовать полученную строку в ДвоичныеДанные 1С.
Выясним, как это реализовать в коде:
// Формируем отсоединенную подпись (флаг Истина)
// Первый параметр: объект Signer
// Второй параметр: 1 (CADESCOM_CADES_BES)
// Третий параметр: Истина (bDetached - отсоединенная подпись)
Попытка
СтрокаПодписиBase64 = CadesSignedData.SignCades(Signer, 1, Истина);
// Преобразуем Base64 в бинарные данные (DER-кодировка)
ПодписьДвоичныеДанные = Base64Значение(СтрокаПодписиBase64);
// Теперь ПодписьДвоичныеДанные можно сохранить в файл .sig
ПодписьДвоичныеДанные.Записать(ПутьКФайлуПодписи);
Сообщить("Подпись успешно сформирована в формате DER");
Исключение
Сообщить("Ошибка при подписании: " + ОписаниеОшибки());
КонецПопытки;
При работе на стороне сервера стоит учитывать еще несколько важных факторов, которые могут влиять на валидность подписи и стабильность работы:
CPSigner по умолчанию проверяет сертификат на отзыв. Если на сервере нет доступа к спискам отзыва (CRL) через интернет, процесс подписания может зависнуть или выдать ошибку. В таких случаях можно использовать свойство Signer.CheckCertificate = Ложь;, однако это снижает безопасность.DisplayData. Это специфично для определенных версий библиотеки, но стоит иметь в виду при возникновении нетипичных ошибок.Таким образом, мы рассмотрели полный цикл создания ЭП: от настройки окружения до получения бинарных данных в формате DER. Использование ContentEncoding = 1 и последующее преобразование Base64Значение() являются ключевыми факторами для получения корректного результата при работе с произвольными файлами. Для решения этой задачи без ручного программирования можно использовать обработку для подписания произвольных файлов сертификатом ЭЦП.