Предлагаемая обработка является существенно переработанной версией другой обработки, опубликованной здесь ранее:
//obrabotki.nsksoft.ru/public/1223640/
Её автор Никита Хацкевич проделал большую работу по переводу обработки с языка C на язык 1С. Однако у неё, на мой взгляд, осталось две проблемы:
1. Формат входных и выходных данных: строки в HEX-формате. Удобнее было бы иметь дело с типом ДвоичныеДанные.
2. Крайне низкая производительность. Когда я попытался использовать модуль "как есть" - быстро понял, что это не получится, т. к. слишком долго. Пришлось засучить рукава и внести свой вклад )
Обе проблемы удалось полностью решить, но от исходной обработки мало что осталось.
Первым делом был изменён тип входных данных - обработка сразу показала неплохой прирост в производительности. Но наиболее существенный прирост был получен за счёт предварительного расчёта всего, что можно было рассчитать. Эти данные были помещены в строку JSON, из которой при запуске полностью формируется готовая структура Const. Производительность выросла на порядок.
Следующей проблемой оказалась функция платформы "ПобитовоеИсключительноеИли" - она оказалась в топе по накладным расходам. Ок - делаем двумерный массив с посчитанными значениями. Но применить тот же приём со строкой JSON не удалось, так как загрузка этой строки стала занимать существенную часть времени. Тогда был применён другой приём - весь массив был записан побайтно в файл и затем загружен в макет. При старте вычислений из макета получается переменная типа ДвоичныеДанные, которая нарезается в массив буферов по 256 байт. Это отрабатывает быстро, но прирост в производительности от замены функции платформы составил всего 1,5-2 раза. Если вам требуется просто модуль, а не обработка, без каких-либо макетов - то стоит заменить обратно "XOR" на вызов типовой функции "ПобитовоеИсключительноеИли".
Ещё некоторое количество миллисекунд удалось выудить за счёт сокращения вложенности вызовов функций. Кое где в ущерб читаемости.
Заметка о самом алгоритме
Шифр блочный и поэтому если входные данные не кратны 16 байтам - "хвостик" забивается нулями. Это не очень хорошо с точки зрения криптостойкости, поэтому лучше, чтобы это были не нули, а случайные значения. Но в этом случае становится непонятна длина исходных данных. Помещать длину в начало или в конец - тоже не очень хорошо. Лучше передавать её отдельно и затем обрезать результат расшифровки до нужной длины.
Данная проблема в обработке не была отработана, так как не всем это нужно.
Тесты
Обработка тестировалась на платформе 1С:Предприятие 8.3 (8.3.16.1502).
Процедура тестирования исходной обработки:
&НаСервере
Процедура ТестСкоростиНаСервере()
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
СчётчикПаролей = 1;
ИсходнаяСтрока = "";
Для ЧислоБлоков = 1 по 32 Цикл
Данные = ПолучитьДанные(ЧислоБлоков);
ДанныеHEX = ПолучитьHexСтрокуИзДвоичныхДанных(Данные);
СреднееВремя = 0;
Для НомерИтерации = 1 по 10 Цикл
Ключ256 = ПолучитьКлюч256(Формат(СчётчикПаролей, ""));
Ключ256_HEX = ПолучитьHexСтрокуИзДвоичныхДанных(Ключ256);
СчётчикПаролей = СчётчикПаролей + 1;
Время1 = ТекущаяУниверсальнаяДатаВМиллисекундах(); // СТАРТ!
РезультатHEX = ОбработкаОбъект.Зашифровать(ДанныеHEX, Ключ256_HEX, 256);
ИсходныеДанные = ОбработкаОбъект.Расшифровать(РезультатHEX, Ключ256_HEX, 256);
Время2 = ТекущаяУниверсальнаяДатаВМиллисекундах(); // СТОП!
СреднееВремя = СреднееВремя + Время2 - Время1;
КонецЦикла;
ТекстСообщения = СтрШаблон(
"%1;%2"
,Формат(ЧислоБлоков, "ЧН=; ЧГ=")
,Формат(СреднееВремя / 10, "ЧРД=,; ЧН=; ЧГ=")
);
Сообщить(ТекстСообщения);
КонецЦикла;
КонецПроцедуры
Результаты. Первый столбец - число блоков в сообщении. Второй столбец - среднее количество миллисекунд, необходимое для зашифровки и расшифровки этого сообщения 256-битным ключом за 10 итераций. Ключ на каждой итерации новый.
Число блоков | млсек |
1 | 1172,7 |
2 | 2095,9 |
3 | 3337,3 |
4 | 4462,9 |
5 | 5461 |
6 | 6124,4 |
7 | 7587,5 |
8 | 9798,7 |
9 | 10776,4 |
10 | 12567,2 |
11 | 13681,9 |
12 | 14596,7 |
13 | 15450,6 |
14 | 16352 |
15 | 17452,1 |
16 | 18694,3 |
17 | 20562,8 |
Процедура тестирования этой обработки:
&НаСервере
Процедура ТестСкоростиНаСервере()
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
СчётчикПаролей = 1;
ИсходнаяСтрока = "";
Для ЧислоБлоков = 1 по 32 Цикл
Данные = ПолучитьДанные(ЧислоБлоков);
СреднееВремя = 0;
Для НомерИтерации = 1 по 10 Цикл
Ключ256 = ПолучитьКлюч256(Формат(СчётчикПаролей, ""));
СчётчикПаролей = СчётчикПаролей + 1;
Время1 = ТекущаяУниверсальнаяДатаВМиллисекундах(); // СТАРТ!
Результат = ОбработкаОбъект.Зашифровать(Данные, Ключ256, 256);
ИсходныеДанные = ОбработкаОбъект.Расшифровать(Результат, Ключ256, 256);
Время2 = ТекущаяУниверсальнаяДатаВМиллисекундах(); // СТОП!
СреднееВремя = СреднееВремя + Время2 - Время1;
КонецЦикла;
ТекстСообщения = СтрШаблон(
"%1;%2"
,Формат(ЧислоБлоков, "ЧН=; ЧГ=")
,Формат(СреднееВремя / 10, "ЧРД=,; ЧН=; ЧГ=")
);
Сообщить(ТекстСообщения);
КонецЦикла;
КонецПроцедуры
Результат. Столбцы те же.
Число блоков | млсек |
1 | 63,7 |
2 | 107,2 |
3 | 142,1 |
4 | 184,1 |
5 | 222,1 |
6 | 253,2 |
7 | 303,8 |
8 | 322,1 |
9 | 396,3 |
10 | 417,3 |
11 | 439,8 |
12 | 495,6 |
13 | 598,3 |
14 | 601,8 |
15 | 680,9 |
16 | 743,9 |
17 | 806,5 |
18 | 847,8 |
19 | 795,7 |
20 | 687 |
21 | 915,6 |
22 | 947,6 |
23 | 927,3 |
24 | 944,6 |
25 | 978,6 |
26 | 1019,1 |
27 | 1076,8 |
28 | 1095,7 |
29 | 1149,2 |
30 | 1251,6 |
31 | 1260,3 |
32 | 1221,4 |
17 блоков - 20562,8 млсек и 806,5. Итого: ускорение в 25,5 раз.
Оба результата в виде графика: