Имя: Пароль:
1C
1С v8
Помогите найти рабочий пример реализации HMACSHA256 в 1С:8.2
,
0 Puzoter
 
13.04.18
11:29
Задача - сделать запрос к сайту с использованием ХЭШа HMACSHA256.
Те примеры, которые я нашел почему-то возвращают результат, отличный от функции hash_hmac() PHP.
1 oleg_km
 
13.04.18
13:32
2 Puzoter
 
13.04.18
14:31
В hash_hmac() PHP используется два параметра - данные и секретный ключ, а в ХешированиеДанных() в 8.3 можно использовать ключ?
3 Puzoter
 
13.04.18
14:32
(1) Это сложно слишком. Проще наверно поднять ПХП и делать к нему ГЕТ запрос.
4 Puzoter
 
13.04.18
15:00
Для получения ХЭШа использую функцию:

Функция ЗашифроватьSHA256(Строка, СекретныйКлюч)

    Соотв16 = Новый Соответствие;
    Соотв16.Вставить(0 , "0");
    Соотв16.Вставить(1 , "1");
    Соотв16.Вставить(2 , "2");
    Соотв16.Вставить(3 , "3");
    Соотв16.Вставить(4 , "4");
    Соотв16.Вставить(5 , "5");
    Соотв16.Вставить(6 , "6");
    Соотв16.Вставить(7 , "7");
    Соотв16.Вставить(8 , "8");
    Соотв16.Вставить(9 , "9");
    Соотв16.Вставить(10, "a");
    Соотв16.Вставить(11, "b");
    Соотв16.Вставить(12, "c");
    Соотв16.Вставить(13, "d");
    Соотв16.Вставить(14, "e");
    Соотв16.Вставить(15, "f");

    Текст = Новый COMОбъект("System.Text.UTF8Encoding");
    //Текст = Новый COMОбъект("System.Text.ASCIIEncoding");

    
    Криптография = Новый COMОбъект("System.Security.Cryptography.HMACSHA256");
    Криптография.Key = Текст.GetBytes_4(СекретныйКлюч);

    ХешБайт = Криптография.ComputeHash_2(Текст.GetBytes_4(Строка)).Выгрузить();

    Хеш = "";
    Для Каждого Байт Из ХешБайт Цикл
        Чс = Цел(Байт/16);
        Хеш = Хеш + Прав("0" + Соотв16.Получить(Чс) + Соотв16.Получить(Байт-Чс*16), 2);
    КонецЦикла;

    Возврат Хеш;

КонецФункции

Функция возвращает строку типа: 41c9dd976bcfd8be539f40c0e250d77cfa5c5637a3acfcc73b853ba7b87591c5
Судя по всему - шеснадцатеричный код
Далее эту строку нужно закодировать эту строку в Base64:

Функция _КодироватьСтрокуВBase64(ИсходнаяСтрока) Экспорт
    ИмяВрФ = ПолучитьИмяВременногоФайла();
    ЗаписьТекста = Новый ЗаписьТекста(ИмяВрФ, КодировкаТекста.ANSI);
    ЗаписьТекста.Записать(ИсходнаяСтрока);
    ЗаписьТекста.Закрыть();
    Результат = Base64Строка(Новый ДвоичныеДанные(ИмяВрФ));
    Попытка
      УдалитьФайлы(ИмяВрФ)
    Исключение
    КонецПопытки;
    Возврат Результат;

конецфункции

На выходе получаем не тот результат, который ожидаем.
Возможно, что шеснадцатеричный код необходимо преобразовать в символьную строку, скорее всего  utf8.

Есть у кого какие соображения на этот счет?

Как шеснадцатеричный код преобразовать в символьную строку utf8?
5 oleg_km
 
13.04.18
15:07
Так ты и так используешь тот класс который я предложил, только через КОМ

Криптография = Новый COMОбъект("System.Security.Cryptography.HMACSHA256");
6 Puzoter
 
13.04.18
15:31
(5) Да только ладу ему не дам с этими кодами и кодировками.
7 Puzoter
 
13.04.18
16:28
В общем ситуация с хешированием следующая:

И функция хэширования System.Security.Cryptography.HMACSHA256
и встроенная функция хэширования 1С: 8.3
возвращают строки типа: 41c9dd976bcfd8be539f40c0e250d77cfa5c5637a3acfcc73b853ba7b87591c5
Судя по всему - шеснадцатеричный код.
Причем строки разные при одинаковых вводных - как так????

Далее полученный хэш нужно закодировать в Base64:

Функция _КодироватьСтрокуВBase64(ИсходнаяСтрока) Экспорт
    ИмяВрФ = ПолучитьИмяВременногоФайла();
    ЗаписьТекста = Новый ЗаписьТекста(ИмяВрФ, КодировкаТекста.ANSI);
    ЗаписьТекста.Записать(ИсходнаяСтрока);
    ЗаписьТекста.Закрыть();
    Результат = Base64Строка(Новый ДвоичныеДанные(ИмяВрФ));
    Попытка
      УдалитьФайлы(ИмяВрФ)
    Исключение
    КонецПопытки;
    Возврат Результат;
Конецфункции

При этом, опять таки, судя по всему, на вход Base64Строка() нужно давать символьную строку.

Вопрос, в какой кодировке?

Допустим в WIN-1251, тогда результат будет AЙЭϧkПШЎSϯ@АвPЧ|ъ\V7ϳϼьЗ;ϕ;ϷЈuϡЕ - длина 32 символа

При этом хэш полученный в PHP: XеИЬНЊ УH:G#O]РzN®6…ЦБ - длина 22 символа

Как же все-таки в 1С получить ХЭШ такой же, как в PHP?
8 tesseract
 
13.04.18
16:56
(7)
>>Судя по всему - шеснадцатеричный код.

Внезапно прямо, никто не ждал, что двоичные данные легко преобразуются в 16-ричный код.

>>Допустим в WIN-1251,

1C работает со строками  utf-8 по умолчанию.  Даже  в документации написано.
9 xXeNoNx
 
13.04.18
17:06
(0)шо там, бота для биржи пишем?
10 Puzoter
 
13.04.18
17:08
(8) ну пусть utf8 - это ничего не меняет. Зачем что-то говорить, если по существу сказать нечего?
11 xXeNoNx
 
13.04.18
17:09
Мож как-нить так?

Функция DecToHex(Знач Число)
    тЧисло = Число;
    тБаза = 16;
    
    Пока тЧисло <> 0 Цикл
        тПоз =тЧисло % тБаза;
        Результат = Сред("0123456789abcdef", тПоз + 1, 1) + Результат;
        тЧисло = Цел(тЧисло / тБаза);
    КонецЦикла;
    
    Если Число < тБаза Тогда
        Результат = "0" + Результат;
    КонецЕсли;
    
    Возврат Результат;
КонецФункции

Функция ПолучитьЗашифрованнуюСтроку(СтрокаШифрования, СекретныйКлюч)
    Текст = Новый COMОбъект("System.Text.UTF8Encoding");
    КриптоSHA512 = Новый COMОбъект("System.Security.Cryptography.HMACSHA512");  
    КриптоSHA512.Key = Текст.GetBytes_4(СекретныйКлюч);
    Хэш = КриптоSHA512.ComputeHash_2(Текст.GetBytes_4(СтрокаШифрования)).Выгрузить();
    
    ХэшСтрокой = "";
    Для Каждого байт ИЗ Хэш Цикл
        ХэшСтрокой = ХэшСтрокой + DecToHex(байт);
    КонецЦикла;
    
    возврат ХэшСтрокой;
    
КонецФункции
12 tesseract
 
13.04.18
17:11
(10)  Странно но любой алгоритм хэширования дает разные данные, в зависимости от кодировки. Может у кодировок в шестнадцатеричном коде коды другие?
13 xXeNoNx
 
13.04.18
17:11
+(11) Запили тока для 256
14 Puzoter
 
13.04.18
17:24
(13) Запилил. Результат отличается от

Функция ПолучитьХЭШ(ИсходнаяСтрока,Ключ)
    Хеширование = Новый ХешированиеДанных(ХешФункция.SHA256);
    Хеширование.Добавить(ИсходнаяСтрока);
    //Хеширование.Добавить(Ключ);
    ТипКлюча = ФабрикаXDTO.Тип("http://www.w3.org/2001/XMLSchema";, "hexBinary");
    ОбъектКлюча = ФабрикаXDTO.Создать(ТипКлюча, Хеширование.ХешСумма);
    СтроковыйКлюч = ОбъектКлюча.ЛексическоеЗначение;
    Если СтрДлина(СтроковыйКлюч) > 64 Тогда
        Сообщить("Превышение дланы ключа");
    КонецЕсли;
    Возврат СтроковыйКлюч;
КонецФункции

Почему?
15 tesseract
 
13.04.18
17:27
(14) потому что (8).
16 Puzoter
 
13.04.18
17:28
И остается вопрос: почему, если результат преобразовать в текст, не зависимо от кодировки строка будет из 32х символов. На сайте PHP ее будет сравнивать со своей строкой, а в ней 22 символа %)
17 Puzoter
 
13.04.18
17:31
(15) Да WIN-1251 я для примера привел, в программном коде эта кодировка нигде не используется. Просто закодировал HEX WIN-1251 и получил строку длиной 32 из сравнения со строкой из PHP. В utf-8 был бы тот же результат.
18 Puzoter
 
13.04.18
17:33
(15) По существу: где там кодировку указывать? И в ту и в другую функцию передается одна и та же строка в кодировке 1С (utf-8)
19 tesseract
 
13.04.18
17:36
>>И остается вопрос: почему, если результат преобразовать в текст, не зависимо от кодировки строка будет из 32х символов.

потому что длина блока у sha-256 - 512 бит. у sha-512 будет 64.

>>В utf-8 был бы тот же результат.

Это тебе Хрюша со Степашкой сказали?

(16) Да нигде -F1 нажми у увидишь что в функцию хеширование должны попадать двоичные данные. А для utf/utf8/utf16/win1251/cp866  они таки разные.
20 Puzoter
 
13.04.18
17:46
(19) Я по-моему ни где ни упоминал sha-512.

В Функции ПолучитьХЭШ(ИсходнаяСтрока,Ключ)
Хеширование = Новый ХешированиеДанных(ХешФункция.SHA256);
Хеширование.Добавить(ИсходнаяСтрока);

ИсходнаяСтрока - символьная, а не двоичная.
21 tesseract
 
13.04.18
17:48
(20) У строки есть двоичные данные. Ее просто неявно преобразуют из UTF-8. Это указано в справке.
22 Сияющий в темноте
 
13.04.18
21:43
Я бы для начала посмотрел бы в интеинете генератор hash,чтобы понять кто из 1с или пхп криво генерит результат,очень похоже,что косячит пхр,т.к.у него по умолчанию однобайтовая кодировка,и если вы строку изначально в ютф8 не готовили,то будет фигня
23 DmitriyDI
 
14.04.18
11:19
(1) вот код работает 100%

Функция ЗашифроватьSHA512(Строка, СекретныйКлюч) Экспорт
    
    Текст = Новый COMОбъект("System.Text.UTF8Encoding");
    Криптография = Новый COMОбъект("System.Security.Cryptography.HMACSHA512");
    Криптография.Key = Текст.GetBytes_4(СекретныйКлюч);
    ХешБайт = Криптография.ComputeHash_2(Текст.GetBytes_4(Строка)).Выгрузить();

    Хеш = "";
    Для Каждого Байт Из ХешБайт Цикл
        Символ = ЗакодироватьСтроку1С(Байт);
        Хеш = Хеш + ?(СтрДлина(Символ) = 2, Символ, "0"+Символ);
    КонецЦикла;
    Возврат НРег(Хеш);
КонецФункции

Функция ЗакодироватьСтроку1С(Знач ВходящееЧисло)
    
    База = 16;
    Результат = "";
    
    Пока ВходящееЧисло <> 0 Цикл
        Поз =ВходящееЧисло % База;
        Результат = Сред("0123456789ABCDEF", Поз + 1, 1) + Результат;
        ВходящееЧисло = Цел(ВходящееЧисло / База);
    КонецЦикла;
    
    Возврат Результат;
    
КонецФункции
24 DmitriyDI
 
14.04.18
11:21
(23) а там 256, сори, тогда не подойдет
Компьютер — устройство, разработанное для ускорения и автоматизации человеческих ошибок.