Как исправить ошибку «Подпись не прошла проверку в crypto» при интеграции 1С с «Честным Знаком»?

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

Интеграция с государственной системой маркировки «Честный Знак» (ГИС МТ) — это сложный процесс, требующий филигранной работы с криптографическими алгоритмами. Часто разработчики сталкиваются с ситуацией, когда авторизация и получение сессионного токена проходят успешно, но при попытке подписать и отправить входящие документы (например, УПД или титулы покупателя) сервер возвращает критическую ошибку: «Подпись не прошла проверку в crypto». В этой статье мы подробно разберем причины возникновения этой проблемы и рассмотрим проверенные способы ее решения с использованием как COM-объектов, так и встроенных средств платформы 1С. В качестве альтернативы ручному написанию кода можно применить готовое программное обеспечение для автоматизации работы с ЭЦП и кодами маркировки.

Разберем разницу между типами подписи

Первое, на что стоит обратить внимание — это различие в требованиях к подписи для разных методов API. Для получения ключа сессии (/api/v1/session) система обычно требует присоединенную подпись. Однако для работы с документами (например, через методы /api/v1/incoming-documents/xml/upd/title) требуется строго открепленная (detached) подпись в формате CAdES-BES.

Проанализируем ключевые моменты: если вы используете одну и ту же функцию для обоих случаев, скорее всего, ошибка кроется в неверном параметре bDetached. Рассмотрим, как это реализовать правильно.

Способ 1: Использование COM-объекта CAdESCOM

Этот метод является классическим для интеграции с КриптоПро. Рассмотрим доработанную функцию, которая исключает лишние атрибуты, часто мешающие проверке на стороне «Честного Знака». Выясним причину: часто штамп времени (Signing Time) вызывает конфликты, если время на сервере 1С и сервере Честного Знака рассинхронизировано даже на несколько секунд.


Функция ПодписатьТекстCAdES(ТекстДляПодписи, ОтпечатокСертификата, ЭтоОткрепленнаяПодпись)
    
    // Константы для работы с CAdESCOM
    CADESCOM_BASE64_TO_BINARY = 1; 
    CADESCOM_CADES_TYPE_BES = 1; 
    CAPICOM_ENCODE_BASE64 = 0;
    
    // Инициализируем объекты
    Попытка
        oSigner = Новый COMОбъект("CAdESCOM.CPSigner");
        oSignedData = Новый COMОбъект("CAdESCOM.CadesSignedData");
    Исключение
        ЗаписьЖурналаРегистрации("Криптография", УровеньЖурналаРегистрации.Ошибка, , , "Библиотека CAdESCOM не установлена.");
        Возврат Неопределено;
    КонецПопытки;
    
    // Получаем сертификат (реализация функции поиска по отпечатку приведена ниже)
    oSigner.Certificate = ПолучитьСертификатПоОтпечатку(ОтпечатокСертификата);
    
    // Важно: для Честного Знака часто лучше не добавлять атрибут времени вручную, 
    // если система этого не требует явно, так как формат BES подразумевает его наличие внутри.
    // Если нужно добавить, используем oSigner.AuthenticatedAttributes2.Add(oSigningTimeAttr);
    
    oSignedData.ContentEncoding = CADESCOM_BASE64_TO_BINARY;
    oSignedData.Content = ТекстДляПодписи; // Текст должен быть в Base64
    
    Попытка
        // Основной метод подписания
        РезультатПодписи = oSignedData.SignCades(oSigner, CADESCOM_CADES_TYPE_BES, ЭтоОткрепленнаяПодпись, CAPICOM_ENCODE_BASE64);
        
        // Очищаем результат от символов переноса строк, которые добавляет COM-объект
        РезультатПодписи = СтрЗаменить(РезультатПодписи, Символы.ПС, "");
        РезультатПодписи = СтрЗаменить(РезультатПодписи, Символы.ВК, "");
        
        Возврат РезультатПодписи;
    Исключение
        Сообщить("Ошибка при формировании подписи: " + ОписаниеОшибки());
        Возврат "";
    КонецПопытки;
    
КонецФункции

Способ 2: Использование встроенного Менеджера Криптографии 1С

Начиная с современных версий платформы 8.3, рекомендуется использовать объект МенеджерКриптографии. Это позволяет избежать проблем с регистрацией COM-компонентов и повышает стабильность системы. Посмотрим на пример реализации открепленной подписи для документов маркировки:


Функция ПодписатьДанныеЧерезМенеджер(ДанныеДляПодписи, Отпечаток)
    
    // Инициализируем менеджер с указанием провайдера ГОСТ 2012
    // Имя провайдера может отличаться в зависимости от установленной версии КриптоПро
    ИмяПровайдера = "Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider";
    ТипПровайдера = 80;
    
    Менеджер = Новый МенеджерКриптографии(ИмяПровайдера, "", ТипПровайдера);
    
    // Ищем сертификат в личном хранилище
    Хранилище = Менеджер.ПолучитьХранилищеСертификатов(ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты);
    ДвоичныйОтпечаток = ПолучитьДвоичныеДанныеИзHexСтроки(Отпечаток);
    МассивСертификатов = Хранилище.НайтиПоОтпечатку(ДвоичныйОтпечаток);
    
    Если МассивСертификатов.Количество() = 0 Тогда
        ВызватьИсключение "Сертификат с указанным отпечатком не найден!";
    КонецЕсли;
    Сертификат = МассивСертификатов[0];
    
    // Для ГИС МТ данные должны быть переданы как ДвоичныеДанные
    Если ТипЗнч(ДанныеДляПодписи) = Тип("Строка") Тогда
        // Обязательно используем UTF-8 БЕЗ BOM
        ДвоичныеДанные = ПолучитьДвоичныеДанныеИзСтроки(ДанныеДляПодписи, КодировкаТекста.UTF8, Ложь);
    Иначе
        ДвоичныеДанные = ДанныеДляПодписи;
    КонецЕсли;
    
    // Формируем открепленную подпись
    // Метод Подписать(Данные, Сертификат) создает отсоединенную подпись в формате CMS (PKCS#7)
    ДД_Подписи = Менеджер.Подписать(ДвоичныеДанные, Сертификат);
    
    // Кодируем в Base64 и удаляем лишние символы
    СтрокаПодписи = Base64Строка(ДД_Подписи);
    СтрокаПодписи = СтрЗаменить(СтрокаПодписи, Символы.ПС, "");
    СтрокаПодписи = СтрЗаменить(СтрокаПодписи, Символы.ВК, "");
    
    Возврат СтрокаПодписи;

КонецФункции

Проанализируем критические нюансы форматирования

Даже если ваш код технически верен, проверка «Честного Знака» может отклонить подпись из-за мельчайших неточностей в подготовке данных. Рассмотрим основные «подводные камни»:

  1. Кодировка UTF-8 без BOM: Это самая частая причина ошибки. Если вы подписываете XML-файл, в начале которого стоит метка BOM (Byte Order Mark), хэш файла будет рассчитан неверно. В 1С при использовании ЗаписьТекста или ПолучитьДвоичныеДанныеИзСтроки всегда указывайте параметр использования BOM как Ложь.
  2. Лишние пробелы и переносы: API Честного Знака ожидает подпись одной сплошной строкой Base64. Стандартный метод Base64Строка() в 1С или COM-объекты могут вставлять символы CRLF (перенос строки) каждые 64 или 72 символа. Их обязательно нужно удалять с помощью СтрЗаменить.
  3. Соответствие тела запроса и подписи: Помните, что подписывать нужно ровно те байты, которые вы отправляете в теле HTTP-запроса. Если вы сформировали XML, подписали его, а затем перед отправкой прогнали через какой-то парсер, который изменил форматирование (например, добавил отступы или изменил порядок атрибутов), подпись станет невалидной.
  4. Тип контента (ContentEncoding): В COM-объекте CadesSignedData свойство ContentEncoding должно быть установлено в 1 (CADESCOM_BASE64_TO_BINARY), если вы передаете в Content уже закодированную строку. Однако надежнее передавать чистые двоичные данные, если платформа это позволяет.

Как проверить валидность подписи самостоятельно?

Если ошибка сохраняется, проанализируем ситуацию методом исключения. Воспользуйтесь следующей инструкцией:

1. Сохраните XML-файл, который вы пытаетесь отправить, на диск в кодировке UTF-8.

2. Подпишите его с помощью утилиты КриптоПро CSP (cryptcp) или через браузерный плагин на официальном сайте КриптоПро (в разделе проверки подписи).

3. Сравните полученную строку Base64 с той, которую генерирует ваш код в 1С. Если строки различаются в начале — ищите проблему в заголовках (атрибутах) подписи. Если они различаются полностью — проблема в исходных данных (кодировка или невидимые символы).

Использование Менеджера Криптографии с правильным указанием провайдера 80 (для ГОСТ 2012) обычно решает большинство проблем, так как 1С автоматически корректно обрабатывает низкоуровневые вызовы API криптопровайдера. Помните, что для успешной интеграции с Честным Знаком важно соблюдать последовательность: Подготовка данных (UTF-8 без BOM) -> Подписание (CAdES-BES, Detached) -> Очистка Base64 от переносов -> Отправка в POST-запросе. Если в процессе настройки обмена возникают и другие сложности, можно использовать практический сборник готовых решений по интеграции 1С с ГИС МТ.

← На главную