При интеграции 1С:Предприятие с внешними веб-сервисами, платежными шлюзами или API социальных сетей программисты часто сталкиваются с необходимостью формирования подписи сообщения по алгоритму HMAC SHA-1. Казалось бы, задача тривиальная, но на практике часто возникает ситуация, когда полученный в 1С хеш не совпадает с результатом онлайн-генераторов или требованиями стороннего сервиса. Ситуация осложняется при работе на 64-битных серверах, где старые COM-компоненты (например, CAPICOM) не поддерживаются.
В этой статье мы подробно разберем, почему возникают расхождения, как правильно обрабатывать длинные ключи и как реализовать надежное решение, работающее на платформе 1С 8.3 x64.
Прежде всего, проанализируем фундаментальную ошибку: использование встроенного объекта 1С ХешированиеДанных для получения HMAC. Рассмотрим код, который часто ошибочно принимают за решение:
ХФ = Новый ХешированиеДанных(ХешФункция.SHA1);
ХФ.Добавить(Строка);
Результат = Base64Строка(ХФ.ХешСумма);
Проблема заключается в том, что ХешированиеДанных вычисляет обычный хеш SHA-1. Алгоритм HMAC (Hash-based Message Authentication Code) — это не просто хеширование текста, это криптографический алгоритм, который использует секретный ключ. Он строится по формуле: SHA1((K XOR opad) + SHA1((K XOR ipad) + message)). Попытка получить HMAC простым добавлением ключа к строке перед хешированием также не даст верного результата.
Выясним причину, по которой «самописные» функции в 1С могут работать с короткими ключами, но выдавать неверный результат с длинными. Согласно стандарту RFC 2104, процедура подготовки ключа (Key) строго регламентирована:
Если ваша реализация в 1С не учитывает это условие, то на длинных ключах (как в примере из темы форума) хеш никогда не совпадет с эталонным.
Посмотрим на ситуацию со стороны обработки строк. 1С хранит строки в формате UTF-16, в то время как большинство внешних систем и онлайн-генераторов ожидают UTF-8. Кроме того, при копировании ключей из браузеров или документации в строку могут попасть невидимые символы, такие как C2 AD (мягкий перенос) или Zero Width Space.
Проанализируем пример из обсуждения: ключ содержит последовательности, которые визуально выглядят как обычный текст, но при детальном рассмотрении содержат символы с кодами, отличными от стандартных. Перед вычислением хеша крайне важно очистить строку ключа и принудительно перевести её в кодировку UTF-8.
Поскольку мы работаем в среде Windows (x64), наиболее эффективным и надежным способом будет обращение к системной библиотеке System.Security.Cryptography через механизм COM. Этот метод гарантирует полное соответствие стандартам RFC и корректную работу с ключами любой длины.
Разберем по шагам реализацию функции на стороне сервера:
Функция ПолучитьHMAC_SHA1(ТекстДанных, СекретныйКлюч) Экспорт
// Используем мост через COM-объект для доступа к .NET
Текст = Новый COMОбъект("System.Text.UTF8Encoding");
Криптография = Новый COMОбъект("System.Security.Cryptography.HMACSHA1");
// Преобразуем входящие строки 1С (UTF-16) в массивы байтов UTF-8
ДанныеБайты = Текст.GetBytes_4(ТекстДанных);
КлючБайты = Текст.GetBytes_4(СекретныйКлюч);
// Устанавливаем ключ. .NET сам выполнит хеширование ключа, если он > 64 байт
Криптография.Key = КлючБайты;
// Вычисляем хеш-сумму
ХешБайты = Криптография.ComputeHash_2(ДанныеБайты);
// Преобразуем результат в Base64 для удобства передачи
Возврат Base64Строка(ХешБайты);
КонецФункции
В данном примере метод GetBytes_4 используется для получения массива байтов. Обратите внимание, что объект HMACSHA1 в .NET автоматически берет на себя всю сложность реализации RFC 2104, включая XOR-операции с ipad и opad.
Если по каким-то причинам использование COM-объектов невозможно (например, работа в среде Linux), нам необходимо реализовать алгоритм вручную. Рассмотрим логику подготовки ключа, которую нужно добавить в вашу функцию:
// Пример подготовки ключа в 1С
Если КлючБайты.Количество() > 64 Тогда
Хеширование = Новый ХешированиеДанных(ХешФункция.SHA1);
Хеширование.Добавить(КлючБайты);
КлючБайты = Хеширование.ХешСумма; // Получаем 20 байт
КонецЕсли;
// Далее ключ дополняется нулями до 64 байт и выполняются XOR операции
Важно помнить, что для выполнения побайтовых операций XOR в 1С 8.3 лучше всего использовать объект COMОбъект("Число") или преобразовывать данные в массив чисел, так как встроенных средств для работы с битами в языке 1С практически нет (до появления расширений в последних версиях платформы).
Если ваш хеш всё еще не совпадает, выполните следующие действия:
ХешСумма — это ДвоичныеДанные, которые можно преобразовать в HEX через СтрЗаменить(Строка(ХешСумма), " ", "") или в Base64Строка().CRLF vs LF). В 1С это часто Символы.ПС, а веб-сервис может ожидать только \n.Используя системные библиотеки .NET, вы минимизируете риск ошибок реализации и обеспечиваете максимальную производительность вашего кода на платформе 1С 8.3 x64.