В современной корпоративной практике автоматизация документооборота часто требует проверки подлинности электронных подписей (ЭЦП) непосредственно внутри учетной системы. Платформа 1С:Предприятие предоставляет мощный инструментарий для взаимодействия с криптопровайдерами, установленными в операционной системе. В рамках данной статьи мы подробно разберем, как программно проверить наличие и валидность цифровой подписи у файла, используя встроенный объект МенеджерКриптографии, а также средства Библиотеки Стандартных Подсистем (БСП) для алгоритмов хеширования SHA-1 и SHA-256.
Перед тем как перейти к написанию кода, давайте разберем структуру файлов подписи. Существует два основных варианта подписания файлов:
document.pdf) остается неизменным. Файл подписи создается отдельно (обычно с расширением .sig, .sgn или .p7s). Для проверки такой подписи системе 1С требуются оба файла: и исходный документ, и файл подписи..sig, а его размер увеличивается, поскольку внутрь помещаются бинарные данные самой подписи и открытый сертификат ключа проверки.Выясним, как программно реализовать проверку для обоих вариантов в среде 1С:Предприятие. При необходимости подготовить подписанные файлы для тестирования или внедрить обратную операцию можно использовать обработку для подписания произвольных файлов ЭЦП.
Для работы с шифрованием и подписями в 1С используется специализированный объект МенеджерКриптографии. Этот объект является программным интерфейсом (API) к криптографическому софту (СКЗИ), установленному на сервере или компьютере пользователя (например, КриптоПро CSP, VipNet CSP или встроенные службы Microsoft). Если мы проверяем стандартные зарубежные подписи на базе алгоритмов SHA-1 или SHA-256 (RSA), в Windows-системах дополнительное СКЗИ чаще всего не требуется — платформа задействует стандартный системный криптопровайдер.
Рассмотрим пример инициализации менеджера криптографии и явного указания алгоритмов шифрования и хеширования через международные идентификаторы объектов (OID). Использование OID гарантирует корректную работу платформы вне зависимости от локализованного имени криптопровайдера.
Для алгоритма SHA-256 используются следующие OID:
2.16.840.1.101.3.4.2.11.2.840.113549.1.1.11Для алгоритма SHA-1:
1.3.14.3.2.261.2.840.113549.1.1.5Напишем процедуру инициализации объекта МенеджерКриптографии:
Функция ПолучитьМенеджерКриптографииSHA256()
// Инициализируем менеджер криптографии без привязки к конкретному имени провайдера
// Платформа подберет подходящий системный криптопровайдер (например, Microsoft Enhanced RSA and AES CSP)
ИмяПровайдера = "";
ТипПровайдера = 24; // PROV_RSA_AES
Менеджер = Новый МенеджерКриптографии(ИмяПровайдера, "", ТипПровайдера);
// Настраиваем OID для алгоритмов SHA-256
Менеджер.АлгоритмХеширования = "2.16.840.1.101.3.4.2.1";
Менеджер.АлгоритмПодписи = "1.2.840.113549.1.1.11";
Возврат Менеджер;
КонецФункции
Проанализируем ситуацию, когда у нас есть два файла: файл данных и файл подписи. Для проверки подлинности мы должны прочитать оба файла в двоичные данные и передать их методу ПроверитьПодпись().
Разберем готовый листинг кода проверки отсоединенной подписи:
Процедура ПроверитьОтсоединеннуюПодписьНаСервере(ПутьКФайлуДанных, ПутьКФайлуПодписи)
МенеджерКрипто = ПолучитьМенеджерКриптографииSHA256();
Попытка
// Читаем файлы в двоичные данные
ДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлуДанных);
ДанныеПодписи = Новый ДвоичныеДанные(ПутьКФайлуПодписи);
Исключение
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Ошибка чтения файлов с диска: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат;
КонецПопытки;
// Переменная для сохранения сертификата, которым был подписан файл
СертификатПодписанта = Неопределено;
Попытка
// Проверяем подпись. Если она невалидна, метод вызовет исключение.
МенеджерКрипто.ПроверитьПодпись(ДанныеФайла, ДанныеПодписи, СертификатПодписанта);
Сообщить("Математическая проверка подписи успешно пройдена!");
Если ЗначениеЗаполнено(СертификатПодписанта) Тогда
// Извлекаем полезную информацию о владельце подписи
Сообщить("Субъект подписи: " + СертификатПодписанта.Субъект);
Сообщить("Удостоверяющий центр: " + СертификатПодписанта.Издатель);
Сообщить("Действителен с: " + СертификатПодписанта.ДатаНачалаДействия + " по " + СертификатПодписанта.ДатаОкончанияДействия);
КонецЕсли;
Исключение
// Ловим ошибку, если подпись не верна или файл был изменен после подписания
Сообщить("ВНИМАНИЕ! Проверка подписи не пройдена. Причина: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецПроцедуры
При работе с присоединенной подписью все данные упакованы внутри одного файла .sig. Для проверки такой подписи в платформе 1С используется тот же метод ПроверитьПодпись(), однако параметры передаются иначе: мы передаем файл подписи во второй параметр метода, а первый параметр (исходные данные) оставляем пустым либо передаем туда пустые двоичные данные. В таком случае криптопровайдер самостоятельно извлечет исходный файл из контейнера подписи.
Посмотрим на пример кода для проверки присоединенной подписи:
Процедура ПроверитьПрисоединеннуюПодписьНаСервере(ПутьКФайлуПрисоединеннойПодписи)
МенеджерКрипто = ПолучитьМенеджерКриптографииSHA256();
Попытка
ДанныеПрисоединеннойПодписи = Новый ДвоичныеДанные(ПутьКФайлуПрисоединеннойПодписи);
Исключение
Сообщить("Ошибка чтения файла подписи: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат;
КонецПопытки;
СертификатПодписанта = Неопределено;
ПустыеДанные = Новый ДвоичныеДанные(""); // Для присоединенной подписи первый параметр пустой
Попытка
МенеджерКрипто.ПроверитьПодпись(ПустыеДанные, ДанныеПрисоединеннойПодписи, СертификатПодписанта);
Сообщить("Присоединенная подпись верна.");
Если ЗначениеЗаполнено(СертификатПодписанта) Тогда
Сообщить("Подписант: " + СертификатПодписанта.Субъект);
КонецЕсли;
Исключение
Сообщить("Ошибка проверки присоединенной подписи: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецПроцедуры
Если в вашей конфигурации развернута БСП (что справедливо для абсолютного большинства типовых конфигураций вроде 1С:ERP, УТ, БП, ЗУП или КА), то самостоятельно писать низкоуровневый код инициализации МенеджерКриптографии не обязательно. В составе БСП есть готовый общий модуль ЭлектроннаяПодпись, который берет на себя рутинную работу по получению настроек криптографии из информационной базы и обработке ошибок. Для быстрого поиска других полезных функций библиотеки и примеров их вызова удобно использовать справочник по методам БСП с примерами кода.
Давайте рассмотрим, как проверить подпись с помощью функций БСП по шагам:
Пример программного кода работы через БСП:
Процедура ПроверитьПодписьЧерезБСП(ПутьКФайлуДанных, ПутьКФайлуПодписи)
// БСП позволяет получить преднастроенный менеджер криптографии
// на основании настроек программы в режиме "1С:Предприятие"
ПараметрыВызова = ЭлектроннаяПодпись.ПараметрыПолученияМенеджераКриптографии();
// В зависимости от контекста выполнения (на клиенте или сервере) получаем менеджер
РезультатПолучения = ЭлектроннаяПодпись.ПолучитьМенеджерКриптографии(ПараметрыВызова);
Если НЕ РезультатПолучения.Успешно Тогда
Сообщить("Не удалось запустить менеджер криптографии: " + РезультатПолучения.ОписаниеОшибки);
Возврат;
КонецЕсли;
МенеджерКриптографии = РезультатПолучения.МенеджерКриптографии;
// Читаем бинарные данные файлов
ДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлуДанных);
ДанныеПодписи = Новый ДвоичныеДанные(ПутьКФайлуПодписи);
// Проверяем подпись средствами БСП
РезультатПроверки = ЭлектроннаяПодпись.ПроверитьПодпись(МенеджерКриптографии, ДанныеФайла, ДанныеПодписи);
// БСП возвращает структурированный результат проверки
Если РезультатПроверки.ПодписьВерна Тогда
Сообщить("ЭЦП подтверждена программным комплексом БСП!");
// В БСП результат содержит коллекцию проверенных сертификатов
Для Каждого СведенияОСертификате Из РезультатПроверки.Сертификаты Цикл
Сообщить("Сертификат принадлежит: " + СведенияОСертификате.КомуВыдан);
Если СведенияОСертификате.Действителен Тогда
Сообщить("Сам сертификат на момент проверки действителен.");
Иначе
Сообщить("Внимание! Сертификат недействителен: " + СведенияОСертификате.ПричинаНедействительности);
КонецЕсли;
КонецЦикла;
Иначе
Сообщить("Ошибка валидации подписи: " + РезультатПроверки.ОписаниеОшибки);
EndIf;
КонецПроцедуры
При внедрении проверки подписей в ваши алгоритмы обязательно учитывайте следующие архитектурные особенности:
ПроверитьПодпись()) гарантирует только одно: документ не изменялся с момента наложения подписи. Однако сам сертификат подписанта на момент проверки может быть просрочен, отозван или выпущен недоверенным удостоверяющим центром. Для полной валидации необходимо также вызывать проверку цепочки доверия сертификата через метод ПроверитьСертификат().rphost, есть права на чтение реестра, доступ к веткам криптографии и хранилищам сертификатов операционной системы.Используя предложенные методы и готовые шаблоны кода, вы сможете без труда интегрировать функционал проверки электронных цифровых подписей в любые бизнес-процессы вашей конфигурации 1С.