При разработке механизмов интеграции, особенно при работе с API, криптографией и формированием электронных подписей (HMAC), программисты часто сталкиваются с необходимостью преобразования строковых данных в двоичный вид. Одной из самых распространенных ошибок является неправильный выбор функции для этого преобразования. В данной статье мы подробно разберем, как работает функция ПолучитьДвоичныеДанныеИзСтроки, почему она не подходит для работы с упакованными строками Base64 и какие альтернативы существуют в платформе 1С:Предприятие 8.3.
Рассмотрим ситуацию, в которой оказался автор темы. Имеется секретный ключ в формате Base64 (например, "EGzS...YA=="). Для того чтобы использовать его в методе РаботаВМоделиСервисаБТС.Подпись(), необходимо передать объект типа ДвоичныеДанные. Автор использует функцию ПолучитьДвоичныеДанныеИзСтроки, но подпись получается неверной.
Выясним причину:
ПолучитьДвоичныеДанныеИзСтроки выполняет текстовое кодирование. Она берет каждый отдельный символ строки ('E', 'G', 'z', 'S') и заменяет его соответствующим кодом из таблицы символов (например, UTF-8). Если в строке 4 символа, на выходе мы получим 4 байта (или больше, в зависимости от кодировки). Для алгоритма HMAC это будет означать, что ключом является именно набор этих символов.ПолучитьДвоичныеДанныеИзBase64Строки выполняет транспортное декодирование. Она воспринимает всю строку целиком как упакованный бинарный объект. Символы Base64 — это лишь способ представить произвольные байты с помощью ограниченного набора печатных знаков. Декодирование превращает строку обратно в те "сырые" байты, которые были в ней зашифрованы.Проанализируем пример. Если мы имеем строку "AQ==":
ПолучитьДвоичныеДанныеИзСтроки мы получим байты символов 'A', 'Q', '=', '='. В шестнадцатеричном виде (UTF-8) это будет: 41 51 3D 3D.ПолучитьДвоичныеДанныеИзBase64Строки мы получим один единственный байт со значением 1 (hex: 01).В платформе 1С существует несколько способов получить двоичные данные из строки Base64. Посмотрим на них подробнее:
Способ 1: Использование Base64Значение
Это классический метод, который существует в платформе очень давно. Первоначально он предназначался для работы с XML-сериализацией.
СекретныйКлюч = Base64Значение(СтрокаКлюча);
Токен = РаботаВМоделиСервисаБТС.Подпись(СекретныйКлюч, СтрокаДляПодписи);
Способ 2: Использование ПолучитьДвоичныеДанныеИзBase64Строки
Это более современный метод, появившийся в версии 8.3.10. Он работает аналогично, но является частью расширенной библиотеки функций для работы с бинарными данными. В современных конфигурациях рекомендуется использовать именно его.
СекретныйКлюч = ПолучитьДвоичныеДанныеИзBase64Строки(СтрокаКлюча);
Токен = РаботаВМоделиСервисаБТС.Подпись(СекретныйКлюч, СтрокаДляПодписи);
Как показала практика автора вопроса, оба этих метода возвращают идентичный результат, который подходит для криптографических функций.
Если вам все же нужно преобразовать обычный текст в байты (например, тело сообщения для подписи), важно помнить о втором и третьем параметрах функции ПолучитьДвоичныеДанныеИзСтроки. Рассмотрим сигнатуру функции:
ПолучитьДвоичныеДанныеИзСтроки(Строка, Кодировка, ДобавлятьBOM)
Проанализируем ситуацию: если ваша внешняя система (например, API банка или веб-сервис на Java/.NET) ожидает строку в кодировке UTF-8 без метки BOM, а 1С по умолчанию или принудительно ее добавит, то хэш-сумма (подпись) от этих данных не совпадет.
Параметр ДобавлятьBOM может принимать значения из системного перечисления ИспользованиеByteOrderMark:
Использовать — BOM будет добавлен в начало последовательности байт.НеИспользовать — данные будут записаны "как есть".Поскольку объект ДвоичныеДанные в 1С является неизменяемым ("черным ящиком"), мы не можем просто так посмотреть его содержимое в отладчике побайтово. Однако мы можем применить несколько хитростей для анализа.
Вариант А: Использование Буфера двоичных данных
Начиная с версии 8.3.9, мы можем легко преобразовать двоичные данные в буфер, который позволяет читать каждый байт. Разберем пример кода для анализа:
ДвоичныеДанные = ПолучитьДвоичныеДанныеИзBase64Строки(СтрокаКлюча);
Буфер = ПолучитьБуферИзДвоичныхДанных(ДвоичныеДанные);
// Прочитаем первые 4 байта
Для Индекс = 0 По Мин(Буфер.Размер - 1, 3) Цикл
Сообщить("Байт №" + Индекс + ": " + Буфер[Индекс]);
КонецЦикла;
Вариант Б: Запись во временный файл
Это классический совет "гуру 1С". Мы можем записать данные на диск и открыть их любым HEX-редактором (например, Notepad++ с плагином Hex-Editor).
ПутьКФайлу = ПолучитьИмяВременногоФайла("bin");
ДвоичныеДанные.Записать(ПутьКФайлу);
// Теперь файл можно изучить сторонними средствами
Подводя итог нашему исследованию, сформулируем основные правила работы:
A-Z, a-z, 0-9, +, /, = — это Base64. Используйте ПолучитьДвоичныеДанныеИзBase64Строки.ПолучитьДвоичныеДанныеИзСтроки, четко указывая кодировку (обычно КодировкаТекста.UTF8).ДвоичныеДанные сравнивается в 1С по значению (содержимому), поэтому Данные1 = Данные2 вернет Истина, если байты внутри идентичны, даже если объекты были созданы из разных источников.Соблюдение этих простых правил позволит избежать долгих часов отладки при реализации криптографических алгоритмов в 1С.