Как исправить ошибку "invalid sign" при отправке POST-запросов с HMAC-SHA512 подписью к API в 1С?

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

При интеграции 1С с внешними веб-сервисами, торговыми площадками и биржами часто используется механизм аутентификации на основе подписи запроса алгоритмом HMAC-SHA512. В процессе отправки запроса сервер может возвращать ошибку проверки подписи (например, {"success":0,"error":"invalid sign"}). Проанализируем причины возникновения этой проблемы и разберем по шагам, как правильно подготовить тело запроса, рассчитать хэш и настроить заголовки.

Причины возникновения ошибки проверки подписи

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

  1. Неполный состав параметров в теле запроса: некоторые API требуют передачи открытого ключа или определенных служебных полей не только в HTTP-заголовках, но и непосредственно в теле POST-запроса (в формате application/x-www-form-urlencoded).
  2. Наличие невидимой метки порядка байтов (BOM): метод HTTPЗапрос.УстановитьТелоИзСтроки при кодировании в UTF-8 может добавлять символы BOM (EF BB BF) в начало тела. Сервер считывает эти байты, из-за чего хэш тела не совпадает с подписью в заголовке.
  3. Некорректный регистр шестнадцатеричной строки (Hex): большинство веб-сервисов ожидают подпись строго в нижнем регистре (lowercase hex), тогда как стандартные функции форматирования могут выдавать верхний регистр.
  4. Ошибки в параметре nonce: значение счетчика или метки времени должно строго увеличиваться с каждым последующим запросом.
  5. Формат секретного ключа: если секретный ключ предоставлен сервисом в виде шестнадцатеричной строки или Base64, его необходимо предварительно декодировать в массив байтов перед инициализацией алгоритма HMAC.

Реализация расчета HMAC-SHA512 в среде Windows

Рассмотрим подробнее реализацию функции шифрования на платформе Windows с использованием стандартных COM-объектов .NET Framework (System.Security.Cryptography.HMACSHA512 и System.Text.UTF8Encoding).


&НаСервере
Функция ЗашифроватьHMACSHA512(Знач СтрокаДанных, Знач СекретныйКлюч)
    Текст = Новый COMОбъект("System.Text.UTF8Encoding");
    Криптография = Новый COMОбъект("System.Security.Cryptography.HMACSHA512");
    
    // Передаем байты секретного ключа
    Криптография.Key = Текст.GetBytes_4(СекретныйКлюч);
    
    // Вычисляем хэш от переданной строки данных
    БайтыДанных = Текст.GetBytes_4(СтрокаДанных);
    ХешБайт = Криптография.ComputeHash_2(БайтыДанных).Выгрузить();
    
    // Преобразуем массив байтов в шестнадцатеричную строку (в нижнем регистре)
    StringBuilder = Новый COMОбъект("System.Text.StringBuilder");
    Для Каждого Байт Из ХешБайт Цикл
        StringBuilder.AppendFormat("{0:x2}", Байт);
    КонецЦикла;
    
    Возврат StringBuilder.ToString();
КонецФункции

Формирование и отправка HTTP-запроса

Посмотрим на пример правильного формирования параметров и заголовков при отправке POST-запроса через объекты HTTPСоединение и HTTPЗапрос.


&НаСервере
Процедура ВыполнитьЗапросКАПИ()
    КлючАпи = "ваш_api_key";
    Секрет = "ваш_secret_key";
    
    // Формируем уникальное значение nonce (например, на основе текущего времени)
    ТекущийNonce = Формат(ТекущаяУниверсальнаяДатаВМиллисекундах(), "ЧГ=0");
    
    // Формируем строку параметров тела POST-запроса
    // Если API требует apiKey в теле запроса, обязательно добавляем его
    ТелоПараметры = "method=getInfo&nonce=" + ТекущийNonce + "&apikey=" + КлючАпи;
    
    // Вычисляем подпись HMAC-SHA512 от строки параметров
    Подпись = ЗашифроватьHMACSHA512(ТелоПараметры, Секрет);
    
    // Инициализируем защищенное HTTPS-соединение
    SSLСоединение = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Неопределено);
    Соединение = Новый HTTPСоединение("api.example.com",,,,, 30, SSLСоединение);
    
    HTTPЗапрос = Новый HTTPЗапрос("/tapi");
    HTTPЗапрос.Заголовки.Вставить("Key", КлючАпи);
    HTTPЗапрос.Заголовки.Вставить("Sign", Подпись);
    HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");
    
    // Отключаем добавление BOM-маркера в начало тела
    HTTPЗапрос.УстановитьТелоИзСтроки(ТелоПараметры, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
    
    // Отправка запроса на сервер
    Ответ = Соединение.ОтправитьДляОбработки(HTTPЗапрос);
    СтрокаОтвета = Ответ.ПолучитьТелоКакСтроку();
    
    // Чтение и разбор ответа JSON
    ЧтениеJSON = Новый ЧтениеJSON;
    ЧтениеJSON.УстановитьСтроку(СтрокаОтвета);
    Результат = ПрочитатьJSON(ЧтениеJSON);
    
    Если Ответ.КодСостояния = 200 Тогда
        // Обработка успешного результата
    Иначе
        ВызватьИсключение "Ошибка API: " + СтрокаОтвета;
    КонецЕсли;
КонецПроцедуры

Ограничения и альтернативные подходы

Разберем важные архитектурные особенности при работе с криптографией в 1С:

  1. Работа на серверах под управлением Linux: COM-объекты System.Security.Cryptography доступны исключительно в среде ОС Windows. При переносе серверной части на Linux вызов COM-объекта приведет к ошибке.
  2. Ограничения стандартного объекта: объект платформы ХешированиеДанных поддерживает стандартные алгоритмы хэширования без секретного ключа (SHA-512, SHA-256), но не реализует вычисление HMAC.
  3. Кроссплатформенные альтернативы: для работы на серверах Linux рекомендуется использовать внешние компоненты, написанные по технологии Native API (C++, Go, Rust), вызов консольной утилиты openssl через метод ЗапуститьПриложение или вынесение криптографических операций в отдельный микросервис-прокси.
← На главную