При интеграции 1С 7.7 с современными веб-сервисами (SMS-шлюзы, банковские API, маркетплейсы) программисты часто сталкиваются с требованием подписывать запросы алгоритмом HMAC-SHA256. Платформа 1С:Предприятие 7.7, созданная задолго до повсеместного внедрения таких стандартов, не имеет встроенных функций для криптографии этого типа. Рассмотрим подробнее, какими способами можно решить эту задачу, используя доступные системные ресурсы и внешние компоненты.
Основная проблема заключается в том, что 1С 7.7 работает в кодировке ANSI (Windows-1251), тогда как большинство современных API требуют, чтобы строка перед хешированием была преобразована в UTF-8. Кроме того, сам алгоритм SHA256 гораздо сложнее старых MD5 или SHA1, и его реализация на чистом встроенном языке 1С была бы крайне медленной. Выясним, как обойти эти ограничения.
Проанализируем наиболее надежный и производительный метод — использование библиотек .NET Framework, которые уже присутствуют в любой современной ОС Windows. Для того чтобы «подружить» 1С 7.7 и .NET, часто используется внешняя компонента NetObjectToIDispatch. Она позволяет обращаться к мощным криптографическим классам напрямую из кода 1С.
Разберем по шагам пример функции, которая вычисляет HMAC-SHA256:
Функция ВычислитьHMAC(КлючAPI, СтрокаДанных)
// Создаем объект для связи с .NET
Врап = СоздатьОбъект("NetObjectToIDispatch45");
Врап.УстЭтоСемерка();
// Получаем доступ к кодировке UTF8
Encoding = Врап.ПолучитьТип("System.Text.Encoding").UTF8;
// Преобразуем ключ и сообщение в байтовые массивы UTF-8
КлючБайты = Encoding.GetBytes(КлючAPI);
СообщениеБайты = Encoding.GetBytes(СтрокаДанных);
// Создаем объект HMACSHA256 с использованием ключа
HMAC = Врап.СоздатьОбъект("System.Security.Cryptography.HMACSHA256", КлючБайты);
// Вычисляем хеш
ХешБайты = HMAC.ComputeHash(СообщениеБайты);
// Преобразуем результат в шестнадцатеричную строку (hex)
BitConverter = Врап.ПолучитьТип("System.BitConverter");
РезультатHex = Нрег(СтрЗаменить(BitConverter.ToString(ХешБайты), "-", ""));
Возврат РезультатHex;
КонецФункции
В этом примере объект System.Security.Cryptography.HMACSHA256 берет на себя всю тяжелую математическую работу. Использование BitConverter позволяет быстро перевести массив байтов в строковое представление, которое обычно и требуется для передачи в заголовках HTTP-запроса.
Если нет возможности регистрировать специализированные компоненты типа NetObjectToIDispatch, можно воспользоваться стандартным системным компонентом MSScriptControl.ScriptControl. Этот объект позволяет исполнять код на языке JScript (аналог JavaScript от Microsoft). Посмотрим на пример реализации:
Рассмотрим пример кода в 1С:
Процедура ПолучитьПодпись()
// Инициализируем ScriptControl
ScrptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl");
ScrptCtrl.Language = "JScript";
// Здесь должен быть текст JS-библиотеки CryptoJS или аналогичной
ТекстСкрипта = "// ... текст библиотеки SHA256 ...";
ScrptCtrl.AddCode(ТекстСкрипта);
// Формируем данные для хеширования
Данные = "messagessinglesms{""target"": ""BAMBOO"", ""text"": ""Hello""}";
СекретныйКлюч = "MyApiKey123";
// Вызываем функцию хеширования из JS
// Предположим, в библиотеке есть функция CryptoJS.HmacSHA256
Подпись = ScrptCtrl.Eval("CryptoJS.HmacSHA256('" + Данные + "', '" + СекретныйКлюч + "').toString(CryptoJS.enc.Hex)");
Сообщить("Подпись: " + Подпись);
КонецПроцедуры
Важный нюанс: Стандартный MSScriptControl работает с движком JScript, который соответствует старым стандартам. При выборе JS-библиотеки убедитесь, что она совместима со старыми браузерами (Internet Explorer 8 и ниже), иначе возникнут ошибки синтаксиса при добавлении кода через AddCode.
В ситуациях, когда работа с COM-объектами затруднена (например, из-за настроек безопасности или разрядности системы), можно прибегнуть к вызову внешнего приложения. В современных версиях Windows (начиная с 7) встроен PowerShell, который также имеет доступ к .NET Framework.
Посмотрим, как можно вычислить хеш через PowerShell, не выходя из 1С:
// Пример вызова через командную строку
Команда = "powershell -command ""[Reflection.Assembly]::LoadWithPartialName('System.Security'); " +
"$hasher = New-Object System.Security.Cryptography.HMACSHA256; " +
"$hasher.Key = [Text.Encoding]::UTF8.GetBytes('" + КлючAPI + "'); " +
"$hash = $hasher.ComputeHash([Text.Encoding]::UTF8.GetBytes('" + СтрокаДанных + "')); " +
"$hash | foreach { $_.ToString('x2') } | Write-Host""";
// Выполняем команду и перенаправляем вывод в файл или считываем через WScript.Shell
ВкШелл = СоздатьОбъект("WScript.Shell");
Выполнение = ВкШелл.Exec(Команда);
Результат = Выполнение.StdOut.ReadAll();
Этот способ хорош тем, что он не требует регистрации никаких дополнительных DLL в системе, так как PowerShell является частью ОС.
Рассмотрим ситуацию, когда нам нужно подготовить строку в UTF-8 для передачи в MSScriptControl или внешнюю утилиту. В 1С 7.7 нет встроенной функции К_UTF8(), но мы можем воспользоваться объектом ADODB.Stream. Проанализируем пример функции конвертации:
Функция ANSI_To_UTF8(Стр)
Стрим = СоздатьОбъект("ADODB.Stream");
Стрим.Type = 2; // Text
Стрим.Charset = "windows-1251";
Стрим.Open();
Стрим.WriteText(Стр);
Стрим.Position = 0;
Стрим.Charset = "utf-8";
Результат = Стрим.ReadText();
Стрим.Close();
Возврат Результат;
КонецФункции
Для реализации HMAC-SHA256 в 1С 7.7 наиболее предпочтительным является Решение 1 (через .NET компоненту), так как оно обеспечивает максимальную скорость и корректную обработку типов данных. Если же вы ограничены в правах на установку компонент, используйте Решение 2 с проверенной JavaScript-библиотекой. Всегда уделяйте внимание кодировке: несоответствие ANSI и UTF-8 — самая частая причина того, что сервер API возвращает ошибку "Invalid Signature".