При интеграции 1С со сторонними веб-сервисами, интернет-магазинами или платежными шлюзами часто требуется сформировать цифровую подпись запроса (хеш по алгоритму HMAC-SHA1) с использованием секретного ключа (Secret Key). Однако при попытке использовать типовой объект ХешированиеДанных результат расчета не совпадает с данными внешнего сервиса или онлайн-генераторов.
Разберем причины возникновения этой проблемы и рассмотрим рабочие способы вычисления правильного значения HMAC-SHA1 в среде 1С:Предприятие.
Проанализируем распространенную ошибку. Разработчики часто пытаются передать ключ и строку последовательно через метод Добавить() объекта ХешированиеДанных:
ХешированиеДанных = Новый ХешированиеДанных(ХешФункция.SHA1);
ХешированиеДанных.Добавить("superkey");
ХешированиеДанных.Добавить("/auth/token/merchants");
ХешДанных = ХешированиеДанных.ХешСумма;
В этом случае платформа 1С выполняет простое последовательное вычисление контрольной суммы от конкатенации двух строк: SHA1("superkey" + "/auth/token/merchants").
Алгоритм HMAC (Hash-based Message Authentication Code) устроен совершенно иначе. Согласно стандарту RFC 2104, он использует двухэтапное хеширование с модификацией ключа специальными байтовыми масками (ipad = 0x36 и opad = 0x5C) по формуле:
HMAC(K, m) = H((K XOR opad) || H((K XOR ipad) || m))
Следовательно, стандартное склеивание строк через ХешированиеДанных.Добавить() принципиально не может дать значение HMAC.
Также обратим внимание на типичные ошибки при подготовке исходных данных:
ЗаписатьJSON() к обычной строке, она автоматически оборачивается в экранированные двойные кавычки (например, "\"/auth/...\""), что полностью искажает итоговый хеш.ЗаписьТекста может добавлять символы перевода строк (CRLF) или метку порядка байтов (BOM), что меняет бинарный поток данных.Если сервер 1С или клиентское рабочее место работает под управлением ОС Windows с установленной средой .NET Framework, мы можем использовать встроенные классы криптографии через интерфейс COM. Это наиболее компактное решение для операционных систем Windows.
Посмотрим на пример реализации функции:
Функция ЗашифроватьHMAC_SHA1(Знач СтрокаСообщения, Знач СекретныйКлюч) Экспорт
// Создаем COM-объекты для работы с кодировкой UTF-8 и алгоритмом HMAC-SHA1
ОбъектКодировки = Новый COMОбъект("System.Text.UTF8Encoding");
ОбъектКриптографии = Новый COMОбъект("System.Security.Cryptography.HMACSHA1");
// Передаем секретный ключ в байтовом виде
ОбъектКриптографии.Key = ОбъектКодировки.GetBytes_4(СекретныйКлюч);
// Получаем массив байтов сообщения и вычисляем HMAC-хеш
БайтыСообщения = ОбъектКодировки.GetBytes_4(СтрокаСообщения);
ХешБайты = ОбъектКриптографии.ComputeHash_2(БайтыСообщения).Выгрузить();
// Преобразуем байтовый массив в шестнадцатеричную (HEX) строку
ИтоговыйХеш = "";
Для Каждого Байт Из ХешБайты Цикл
СимволHex = DecToHex(Байт);
ИтоговыйХеш = ИтоговыйХеш + ?(СтрДлина(СимволHex) = 2, СимволHex, "0" + СимволHex);
КонецЦикла;
Возврат НРег(ИтоговыйХеш);
КонецФункции
Функция DecToHex(Знач Число)
База = 16;
Результат = "";
СимволыHex = "0123456789abcdef";
Пока Число > 0 Цикл
Остаток = Число % База;
Результат = Сред(СимволыHex, Остаток + 1, 1) + Результат;
Число = Цел(Число / База);
КонецЦикла;
Возврат ?(Результат = "", "00", Результат);
КонецФункции
Разберем особенности работы данного кода:
GetBytes_4 и ComputeHash_2).СекретныйКлюч = "superkey" и СтрокаСообщения = "/auth/token/merchants" функция вернет точное значение 62e37f6dc60083ba969f06ec2276a8682bec227b.Если сервер 1С:Предприятие работает под управлением Linux или в режиме веб-клиента, использование COM-объектов невозможно. В современных версиях платформы 1С:Предприятие (начиная с 8.3.10) задачу можно решить штатным встроенным языком с помощью объектов БуферДвоичныхДанных и ДвоичныеДанные.
Рассмотрим пошаговый алгоритм:
ДвоичныеДанные в кодировке UTF-8 без BOM с помощью метода ПолучитьДвоичныеДанныеИзСтроки().ХешированиеДанных(ХешФункция.SHA1); если меньше — дополняем нулевыми байтами справа до 64 байт.ipad (заполненную байтами 0x36) и внешнюю маску opad (заполненную байтами 0x5C).ЗаписатьПобитовоеИсключительноеИли(), получая блоки K_ipad и K_opad.ПолучитьHexСтрокуИзДвоичныхДанных() или в Base64 через Base64Строка() в зависимости от требований стороннего сервиса.Такой подход обеспечивает полную независимость от операционной системы и корректно работает на любых конфигурациях и платформах 1С.