Как реализовать хэширование HMAC-SHA1 и MD5 в 1С для интеграции с сервисом Аэрофлот Бонус?

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

При интеграции систем на платформе 1С с API программы лояльности «Аэрофлот Бонус» разработчики часто сталкиваются с проблемой: сформированная подпись запроса не совпадает с контрольным примером сервиса. Выясним причину этой проблемы и разберем по шагам правильную реализацию криптографического алгоритма на 1С.

Анализ алгоритма формирования подписи

В эталонной реализации сервиса (написанной на языке Python) для подписи запросов используется алгоритм HMAC-SHA1, в котором в качестве ключа выступает MD5-хэш пин-кода партнера, а в качестве данных — конкатенация параметров транзакции:


msg = str(login) + str(nonce) + str(int(round(float(amount) * rate)))
key = pincode_md5
signature = hmac.new(msg=msg, key=key, digestmod=hashlib.sha1).hexdigest()

Рассмотрим подробнее ключевые нюансы, из-за которых результат в 1С может отличаться от контрольного значения:

  1. Неразрывные пробелы при преобразовании чисел в строки: В 1С стандартная функция Строка(Число) форматирует числа с разделителями групп разрядов (например, "1 000" вместо "1000"). Для формирования строки сообщения необходимо использовать Формат(Число, "ЧГ=0").
  2. Регистр MD5-хэша: Метод hexdigest() в Python возвращает 32-значную шестнадцатеричную строку в нижнем регистре (hex-lowercase). Если в 1С хэш-сумма пин-кода останется в верхнем регистре, HMAC-SHA1 вернет неверный дайджест.
  3. Формат ключа HMAC: Ключом для HMAC-SHA1 должна служить текстовая строка (32 hex-символа MD5 в нижнем регистре), переведенная в байты UTF-8, а не «сырые» 16 байт бинарного хэша.
  4. Кодировка и сигнатура BOM: Преобразование строк в двоичные данные должно выполняться строго в кодировке UTF-8 без добавления маркера последовательности байтов (BOM).
  5. Округление сумм: Функция round() в Python 3 использует банковское округление (к ближайшему четному числу). В 1С по умолчанию используется математическое округление (РежимОкругления.Окр15как20). При расчете итогового значения суммы важно учитывать правила округления на стороне сервиса.

Пошаговая реализация на платформе 1С:Предприятие 8.3

Начиная с версии платформы 8.3.10, в 1С доступен встроенный объект ХешированиеДанных с поддержкой вычисления HMAC при передаче секретного ключа вторым параметром конструктора. Разберем реализацию расчетной функции по шагам.

  1. Вычисление MD5-хэша для пин-кода партнера:

    Сначала преобразуем строку пин-кода в двоичные данные UTF-8 без BOM и рассчитаем хэш MD5, обязательно приведя результат к нижнему регистру.

    
    Функция ПолучитьMD5Строки(Знач ИсходнаяСтрока)
        ДвоичныеДанныеСтроки = ПолучитьДвоичныеДанныеИзСтроки(ИсходнаяСтрока, КодировкаТекста.UTF8, Ложь);
        Хеширование = Новый ХешированиеДанных(ХешФункция.MD5);
        Хеширование.Добавить(ДвоичныеДанныеСтроки);
        Возврат НРег(Хеширование.ХешСумма);
    КонецФункции
    
  2. Сборка строки сообщения для подписи:

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

    
    Функция СформироватьСообщение(Логин, Nonce, Сумма, Курс)
        // Рассчитываем целочисленное значение суммы
        РасчетнаяСумма = Окр(Сумма * Курс, 0, РежимОкругления.Окр15как20);
        
        // Форматируем числа без пробелов и разделителей
        СтрокаNonce = Формат(Nonce, "ЧГ=0");
        СтрокаСуммы = Формат(РасчетнаяСумма, "ЧГ=0");
        
        СтрокаСообщения = СокрЛП(Логин) + СтрокаNonce + СтрокаСуммы;
        Возврат СтрокаСообщения;
    КонецФункции
    
  3. Вычисление итоговой подписи HMAC-SHA1:

    Инициализируем объект ХешированиеДанных с алгоритмом ХешФункция.SHA1 и передаем двоичные данные MD5-ключа в конструктор.

    
    Функция ПолучитьПодписьАэрофлотБонус(Логин, ПинКод, Nonce, Сумма, Курс) Экспорт
        // Шаг 1: Получаем MD5 от пин-кода в нижнем регистре
        MD5КлючСтрока = ПолучитьMD5Строки(СокрЛП(ПинКод));
        
        // Шаг 2: Формируем двоичные данные ключа в UTF-8
        ДвоичныеДанныеКлюча = ПолучитьДвоичныеДанныеИзСтроки(MD5КлючСтрока, КодировкаТекста.UTF8, Ложь);
        
        // Шаг 3: Собираем строку сообщения и переводим в двоичные данные
        СтрокаСообщения = СформироватьСообщение(Логин, Nonce, Сумма, Курс);
        ДвоичныеДанныеСообщения = ПолучитьДвоичныеДанныеИзСтроки(СтрокаСообщения, КодировкаТекста.UTF8, Ложь);
        
        // Шаг 4: Вычисляем HMAC-SHA1
        ХешированиеHMAC = Новый ХешированиеДанных(ХешФункция.SHA1, ДвоичныеДанныеКлюча);
        ХешированиеHMAC.Добавить(ДвоичныеДанныеСообщения);
        
        // Возвращаем хэш в нижнем регистре
        Возврат НРег(ХешированиеHMAC.ХешСумма);
    КонецФункции
    

Альтернативный вариант для платформ 1С ниже версии 8.3.10

Если конфигурация работает на старых версиях платформы 1С, где объект ХешированиеДанных еще не поддерживал секретные ключи для HMAC, расчет можно выполнить через вызов COM-объектов .NET Framework:


Функция ПолучитьHMACSHA1_COM(Знач СтрокаСообщения, Знач СтрокаКлюча)
    Кодировка = Новый COMОбъект("System.Text.UTF8Encoding");
    HMAC = Новый COMОбъект("System.Security.Cryptography.HMACSHA1");
    
    БайтыКлюча = Кодировка.GetBytes_4(СтрокаКлюча);
    HMAC.Key = БайтыКлюча;
    
    БайтыСообщения = Кодировка.GetBytes_4(СтрокаСообщения);
    ХешБайты = HMAC.ComputeHash_2(БайтыСообщения);
    
    // Преобразуем массив байтов в hex-строку
    BitConverter = Новый COMОбъект("System.BitConverter");
    HexСтрока = BitConverter.ToString(ХешБайты);
    HexСтрока = СтрЗаменить(HexСтрока, "-", "");
    
    Возврат НРег(HexСтрока);
КонецФункции

Применение штатных средств платформы с контролем кодировок и отключением разделителей разрядов гарантирует полное совпадение результатов хэширования между 1С и сервисом «Аэрофлот Бонус».

← На главную