SHA512 и HMAC512 на 1С 8 без использования внешних компонент

09.04.22

Разработка - Защита ПО и шифрование

Имплементация алгоритма расчета Hash 512 с ключом и без. С ключом по алгоритму HMAC. Используются механизмы платформы начиная с версии 8.3.11.

Скачать файлы

Наименование Файл Версия Размер
SHA512 и HMAC512 на 1С 8 без использования внешних компонент:
.epf 17,98Kb
114
.epf 1.0 17,98Kb 114 Скачать бесплатно

Во встроенном языке текущей версии, на момент публикации нет штатных средств для расчета Хеша по алгоритму SHA-512, кроме того, нет встроенных механизмов для реализации HMAC, в частности HMAC512, приведённый пример кода позволяет получать хеш сообщения с ключом и без ключа.

В примере приведены вспомогательные функции для обеспечения побитовых операций над 64-х разрядными числами. А также функция расчета хеша SHA512 в которую передаются двоичные данные, для которых нужно рассчитать хеш. Хеш возвращается в виде Hex строки.
Функция HMAC512 рассчитывает хеш с ключом, в эту функцию передаются два строковых параметра - ключ и данные. Возвращает hex строку с хешем.

Алгоритмы расчета SHA-512 и HMAC находятся в общедоступных источниках, например есть соответствующие статьи в википедии, но вариантов реализации этих алгоритмов средствами встроенного языка 1С:Предприятие 8, версии 8.3.11 в открытом доступе не обнаружено. 

Вы можете просто вставить код примера в модуль и вызывать нужные функции.

В коде используются функции языка, появившиеся в релизе платформы 8.3.11, например ПобитовоеНе, однако эти функции позволяют работать только с 32-х разрядными целыми числами.

В приведённом примере реализованы функции для работы с 64-х разрядными числами.

Текст кода имплементации:

Функция ПовторитьСтроку(Строка, Количество)
	
	Части = Новый Массив();
	Для к = 1 По Количество Цикл
		Части.Добавить(Строка);
	КонецЦикла;
	
	Возврат СтрСоединить(Части, "");
	
КонецФункции

Функция СклеитьДвоичныеДанные(ДвоичныеДанные1, ДвоичныеДанные2)
	
	МассивДвоичныхДанных = Новый Массив;
	МассивДвоичныхДанных.Добавить(ДвоичныеДанные1);
	МассивДвоичныхДанных.Добавить(ДвоичныеДанные2);
	
	Возврат СоединитьДвоичныеДанные(МассивДвоичныхДанных);
	
КонецФункции

// Функция получает массив буферов двоичных данных из HEX строки с разделителями запятыми
// пример: "428A2F98,71374491,B5C0FBCF"
//
Функция ПолучитьМассивБДДИзHexСтроки(Знач пСтрока)
	лПоз = Найти(пСтрока,",");
	лМассив = Новый Массив();
	Пока лПоз>1 Цикл
		лПодстрока = Сред(пСтрока,1,лПоз-1);
		пСтрока = Сред(пСтрока,лПоз+1);
		лПоз = Найти(пСтрока,",");
		лМассив.Добавить(ПолучитьБуферДвоичныхДанныхИзHexСтроки(лПодстрока));
	КонецЦикла;
	лМассив.Добавить(ПолучитьБуферДвоичныхДанныхИзHexСтроки(пСтрока));
	Возврат лМассив;
КонецФункции // ПолучитьМассивБДДИзHexСтроки(Знач пСтрока)

// функция осуществляет циклический сдвиг влево
// в данном случае не используется, но пусть будет
Функция ЦиклическийСдвигВлево64(пЧисло, пСмещение)
	Возврат(ПобитовыйСдвигВправо64(пЧисло, 64-пСмещение) + ПобитовыйСдвигВлево64(пЧисло, пСмещение));
КонецФункции // ЦиклическийСдвигВлево64(пЧисло, пСмещение)

// функция осуществляет циклический сдвиг вправо
//
Функция ЦиклическийСдвигВправо64(пЧисло, пСмещение)
	Возврат(ПобитовыйСдвигВправо64(пЧисло, пСмещение) + ПобитовыйСдвигВлево64(пЧисло,64-пСмещение));
КонецФункции // ЦиклическийСдвигВправо64(пЧисло, пСмещение)

Функция ПобитовыйСдвигВправо64(пЧисло, пСмещение)
	лЧисло0 = Цел(пЧисло/4294967296);
	лЧисло1 = пЧисло%4294967296;
	Если пСмещение<32 Тогда
		Возврат (ПобитовыйСдвигВправо(лЧисло0, пСмещение))*4294967296+
		ПобитовыйСдвигВправо(лЧисло1, пСмещение)+ПобитовыйСдвигВлево(лЧисло0, 32-пСмещение);
	ИНаче
		Возврат ПобитовыйСдвигВправо(лЧисло0, пСмещение - 32);
	КонецЕсли;
КонецФункции // ПобитовыйСдвигВправо64(пЧисло, пСмещение)

Функция ПобитовыйСдвигВлево64(пЧисло, пСмещение)
	лЧисло0 = Цел(пЧисло/4294967296);
	лЧисло1 = пЧисло%4294967296;
	Если пСмещение<32 Тогда
		Возврат (ПобитовыйСдвигВлево(лЧисло0, пСмещение)+ПобитовыйСдвигВправо(лЧисло1, 32-пСмещение))*4294967296+
		ПобитовыйСдвигВлево(лЧисло1, пСмещение);
	ИНаче
		Возврат ПобитовыйСдвигВлево(лЧисло1, пСмещение - 32)*4294967296;
	КонецЕсли;
КонецФункции // ПобитовыйСдвигВлево64(пЧисло, пСмещение)

Функция ПобитовоеИсключительноеИли64(пЧисло1, пЧисло2)
	лЧисло10 = Цел(пЧисло1/4294967296);
	лЧисло11 = пЧисло1%4294967296;
	лЧисло20 = Цел(пЧисло2/4294967296);
	лЧисло21 = пЧисло2%4294967296;
	Возврат (ПобитовоеИсключительноеИли(лЧисло10,лЧисло20)*4294967296+ПобитовоеИсключительноеИли(лЧисло11,лЧисло21));
КонецФункции // ПобитовоеИсключительноеИли64(пЧисло1, пЧисло2)

Функция ПобитовоеИ64(пЧисло1, пЧисло2)
	лЧисло10 = Цел(пЧисло1/4294967296);
	лЧисло11 = пЧисло1%4294967296;
	лЧисло20 = Цел(пЧисло2/4294967296);
	лЧисло21 = пЧисло2%4294967296;
	Возврат (ПобитовоеИ(лЧисло10,лЧисло20)*4294967296+ПобитовоеИ(лЧисло11,лЧисло21));
КонецФункции // ПобитовоеИ64(пЧисло1, пЧисло2)

Функция ПобитовоеНе64(пЧисло1)
	лЧисло10 = Цел(пЧисло1/4294967296);
	лЧисло11 = пЧисло1%4294967296;
	Возврат (ПобитовоеНе(лЧисло10)*4294967296+ПобитовоеНе(лЧисло11));
КонецФункции // ПобитовоеНе64(пЧисло1)

Функция ПривестиК64Битам(пЧисло)
	Возврат пЧисло%18446744073709551616;
КонецФункции // ПривестиК64Битам(пЧисло)

// Функция расчета Хеша по алгоритму SHA-512
// Входной параметр - двоичные данные
// Возвращаяет HEX строку с хешем
//
Функция SHA512(пДвоичныеДанные) Экспорт
	//Пояснения:
	// Все переменные беззнаковые, имеют размер 64 бита и при вычислениях суммируются по модулю 2^64
	// message — исходное двоичное сообщение
	// m — преобразованное сообщение
	
	// Инициализация переменных
	// (первые 64 бита дробных частей квадратных корней первых восьми простых чисел [от 2 до 19]):
	h0 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("6a09e667f3bcc908");
	h1 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("bb67ae8584caa73b");
	h2 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("3c6ef372fe94f82b");
	h3 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("a54ff53a5f1d36f1");
	h4 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("510e527fade682d1");
	h5 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("9b05688c2b3e6c1f");
	h6 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("1f83d9abfb41bd6b");
	h7 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("5be0cd19137e2179");
	
	//Таблица констант
	//(первые 64 бита дробных частей кубических корней первых 80 простых чисел [от 2 до 409]):
	
	лСтрока = "
	|428a2f98d728ae22,7137449123ef65cd,b5c0fbcfec4d3b2f,e9b5dba58189dbbc,
	|3956c25bf348b538,59f111f1b605d019,923f82a4af194f9b,ab1c5ed5da6d8118,
	|d807aa98a3030242,12835b0145706fbe,243185be4ee4b28c,550c7dc3d5ffb4e2,
	|72be5d74f27b896f,80deb1fe3b1696b1,9bdc06a725c71235,c19bf174cf692694,
	|e49b69c19ef14ad2,efbe4786384f25e3,0fc19dc68b8cd5b5,240ca1cc77ac9c65,
	|2de92c6f592b0275,4a7484aa6ea6e483,5cb0a9dcbd41fbd4,76f988da831153b5,
	|983e5152ee66dfab,a831c66d2db43210,b00327c898fb213f,bf597fc7beef0ee4,
	|c6e00bf33da88fc2,d5a79147930aa725,06ca6351e003826f,142929670a0e6e70,
	|27b70a8546d22ffc,2e1b21385c26c926,4d2c6dfc5ac42aed,53380d139d95b3df,
	|650a73548baf63de,766a0abb3c77b2a8,81c2c92e47edaee6,92722c851482353b,
	|a2bfe8a14cf10364,a81a664bbc423001,c24b8b70d0f89791,c76c51a30654be30,
	|d192e819d6ef5218,d69906245565a910,f40e35855771202a,106aa07032bbd1b8,
	|19a4c116b8d2d0c8,1e376c085141ab53,2748774cdf8eeb99,34b0bcb5e19b48a8,
	|391c0cb3c5c95a63,4ed8aa4ae3418acb,5b9cca4f7763e373,682e6ff3d6b2b8a3,
	|748f82ee5defb2fc,78a5636f43172f60,84c87814a1f0ab72,8cc702081a6439ec,
	|90befffa23631e28,a4506cebde82bde9,bef9a3f7b2c67915,c67178f2e372532b,
	|ca273eceea26619c,d186b8c721c0c207,eada7dd6cde0eb1e,f57d4f7fee6ed178,
	|06f067aa72176fba,0a637dc5a2c898a6,113f9804bef90dae,1b710b35131c471b,
	|28db77f523047d84,32caab7b40c72493,3c9ebe0a15c9bebc,431d67c49c100d4c,
	|4cc5d4becb3e42b6,597f299cfc657e2a,5fcb6fab3ad6faec,6c44198c4a475817";
	Конст = ПолучитьМассивБДДИзHexСтроки(лСтрока);
	
	//Предварительная обработка:
	//m := m ǁ [k нулевых бит], где k — наименьшее неотрицательное число, такое что 
	//                 (L + 1 + K) mod 1024 = 960, где L — число бит в сообщении (сравнима по модулю 1024 c 960)
	//m := m ǁ Длина(message) — длина исходного сообщения в битах в виде 64-битного числа
	//            с порядком байтов от старшего к младшему

	// Исправлено 2022-04-09	
	//msg = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(пДвоичныеДанные);
	//L = msg.Размер*8; // получаем размер в битах
	//K1 = 1024 - ((L + 64 + 1) % 1024); // сколько бит нужно добавить
	//K = K1 - 7; // Потому что засчитали один бит, а добавлять будем целый байт с лидирующим битом
	//КолвоHEX = K/8; // считаем количество добавляемых байтов
	// /Исправлено 2022-04-09

    msg = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(пДвоичныеДанные);
    L = msg.Размер*8; // получаем размер в битах
    лРазмер = msg.Размер%128;
    K1 = 112 - лРазмер;
    Если лРазмер > 111 Тогда
        K1 = K1 + 128;
    КонецЕсли;
    КолвоHEX = K1 + 7; // Потому что засчитали один бит, а добавлять будем целый байт с лидирующим битом

	лБуферДвДанных = Новый БуферДвоичныхДанных(КолвоHEX,ПорядокБайтов.BigEndian);
	лМассивБухДвДанных = Новый Массив();
	лМассивБухДвДанных.Добавить(msg);
	лМассивБухДвДанных.Добавить(ПолучитьБуферДвоичныхДанныхИзHexСтроки("80"));
	лМассивБухДвДанных.Добавить(лБуферДвДанных);
	
	лБуферДвДанных2 = Новый БуферДвоичныхДанных(8,ПорядокБайтов.BigEndian);
	
	лБуферДвДанных2.ЗаписатьЦелое64(0,L,ПорядокБайтов.BigEndian);
	лМассивБухДвДанных.Добавить(лБуферДвДанных2);
	
	msg = СоединитьБуферыДвоичныхДанных(лМассивБухДвДанных,,ПорядокБайтов.BigEndian);
	
	//разбить сообщение на куски по 512 бит
	лМассив = РазделитьДвоичныеДанные(ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(msg),128);
	
	h_0 = h0.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_1 = h1.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_2 = h2.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_3 = h3.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_4 = h4.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_5 = h5.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_6 = h6.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_7 = h7.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	
	//Далее сообщение обрабатывается последовательными порциями по 1024 бит:
	Для Каждого лКусок1 Из лМассив Цикл
		//    разбить кусок на 16 слов длиной 64 бита (с порядком байтов от старшего к младшему внутри слова): w[0..15]
		лМассив2 = РазделитьДвоичныеДанные(лКусок1,8);
		
		Для i=16 По 79 Цикл
			лЦел15 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(лМассив2[i-15]).ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
			лЦел2 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(лМассив2[i-2]).ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
			//    Сгенерировать дополнительные 48 слов:
			//    для i от 16 до 63
			//        s0 := (w[i-15] rotr 7) xor (w[i-15] rotr 18) xor (w[i-15] shr 3)
			//        s1 := (w[i-2] rotr 17) xor (w[i-2] rotr 19) xor (w[i-2] shr 10)
			//        w[i] := w[i-16] + s0 + w[i-7] + s1
			s0 = ПобитовоеИсключительноеИли64(ПобитовоеИсключительноеИли64(ЦиклическийСдвигВправо64(лЦел15,1),ЦиклическийСдвигВправо64(лЦел15,8)),ПобитовыйСдвигВправо64(лЦел15,7));
			s1 = ПобитовоеИсключительноеИли64(ПобитовоеИсключительноеИли64(ЦиклическийСдвигВправо64(лЦел2,19),ЦиклическийСдвигВправо64(лЦел2,61)),ПобитовыйСдвигВправо64(лЦел2,6));
			лБуфер64 = Новый БуферДвоичныхДанных(8,ПорядокБайтов.BigEndian);
			лЦел64 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(лМассив2[i-16]).ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian) + s0 + ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(лМассив2[i-7]).ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian) + s1;
			лЦел64 = ПривестиК64Битам(лЦел64);
			лБуфер64.ЗаписатьЦелое64(0,лЦел64,ПорядокБайтов.BigEndian);
			лМассив2.Добавить(ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(лБуфер64));
		КонецЦикла;
		
		//    Инициализация вспомогательных переменных:
		a = h_0;
		b = h_1;
		c = h_2;
		d = h_3;
		e = h_4;
		f = h_5;
		g = h_6;
		h = h_7;
		//    Основной цикл:
		
		Для i = 0 По 79 Цикл
			S0 = ПривестиК64Битам(ПобитовоеИсключительноеИли64(ПобитовоеИсключительноеИли64(ЦиклическийСдвигВправо64(a, 28), ЦиклическийСдвигВправо64(a, 34)), ЦиклическийСдвигВправо64(a, 39)));
			Ma = ПривестиК64Битам(ПобитовоеИсключительноеИли64(ПобитовоеИсключительноеИли64(ПобитовоеИ64(a, b), ПобитовоеИ64(a, c)), ПобитовоеИ64(b, c)));
			t2 = ПривестиК64Битам(S0 + Ma);
			S1 = ПривестиК64Битам(ПобитовоеИсключительноеИли64(ПобитовоеИсключительноеИли64(ЦиклическийСдвигВправо64(e, 14), ЦиклическийСдвигВправо64(e, 18)), ЦиклическийСдвигВправо64(e, 41)));
			Ch = ПривестиК64Битам(ПобитовоеИсключительноеИли64(ПобитовоеИ64(e, f), ПобитовоеИ64(ПобитовоеНе64(e), g)));
			t1 = ПривестиК64Битам(h + S1 + Ch + Конст[i].ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian) + ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(лМассив2[i]).ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian));
			h = g;
			g = f;
			f = e;
			e = ПривестиК64Битам(d + t1);
			d = c;
			c = b;
			b = a;
			a = ПривестиК64Битам(t1 + t2);
			
		КонецЦикла;
		
		//    Добавить полученные значения к ранее вычисленному результату:
		h_0 = ПривестиК64Битам(h_0 + a);
		h_1 = ПривестиК64Битам(h_1 + b);
		h_2 = ПривестиК64Битам(h_2 + c);
		h_3 = ПривестиК64Битам(h_3 + d);
		h_4 = ПривестиК64Битам(h_4 + e);
		h_5 = ПривестиК64Битам(h_5 + f);
		h_6 = ПривестиК64Битам(h_6 + g);
		h_7 = ПривестиК64Битам(h_7 + h);
	КонецЦикла;
	
	h0.ЗаписатьЦелое64(0,h_0,ПорядокБайтов.BigEndian);
	h1.ЗаписатьЦелое64(0,h_1,ПорядокБайтов.BigEndian);
	h2.ЗаписатьЦелое64(0,h_2,ПорядокБайтов.BigEndian);
	h3.ЗаписатьЦелое64(0,h_3,ПорядокБайтов.BigEndian);
	h4.ЗаписатьЦелое64(0,h_4,ПорядокБайтов.BigEndian);
	h5.ЗаписатьЦелое64(0,h_5,ПорядокБайтов.BigEndian);
	h6.ЗаписатьЦелое64(0,h_6,ПорядокБайтов.BigEndian);
	h7.ЗаписатьЦелое64(0,h_7,ПорядокБайтов.BigEndian);
	
	//Получить итоговое значение хеша:
	//digest = hash = h0 ǁ h1 ǁ h2 ǁ h3 ǁ h4 ǁ h5 ǁ h6 ǁ h7
	лМассив3 = Новый Массив();
	лМассив3.Добавить(h0);
	лМассив3.Добавить(h1);
	лМассив3.Добавить(h2);
	лМассив3.Добавить(h3);
	лМассив3.Добавить(h4);
	лМассив3.Добавить(h5);
	лМассив3.Добавить(h6);
	лМассив3.Добавить(h7);
	Буфер3 = СоединитьБуферыДвоичныхДанных(лМассив3);
	
	
	digest = Нрег(ПолучитьHexСтрокуИзБуфераДвоичныхДанных(Буфер3));
	
	Возврат digest;
	
КонецФункции // SHA512(пДвоичныеДанные)

// Функция расчета Хеша по алгоритму SHA-512 с ключем
// Входные параметры:
// пКлюч - строка с ключем, неограниченная, приводится к длине блока - 128
// пДанные - строка с данными, неограниченная
// Возвращаяет Hex строку с хешем
//
Функция HMAC512(пКлюч, пДанные) Экспорт
	
	ДанныеДв = ПолучитьДвоичныеДанныеИзСтроки(пДанные);
	КлючДв = ПолучитьДвоичныеДанныеИзСтроки(пКлюч);
	РазмерБлока = 128; // Размер блока для HMAC512 - 128
	
	Если КлючДв.Размер() > РазмерБлока Тогда
		КлючHex = SHA512(КлючДв);
	Иначе
		КлючHex = ПолучитьHexСтрокуИзДвоичныхДанных(КлючДв);
		Если КлючДв.Размер() < РазмерБлока Тогда
			КлючHex = Лев(КлючHex + ПовторитьСтроку("00", РазмерБлока), РазмерБлока);
		КонецЕсли;
	КонецЕсли;
	
	КлючБуфер = ПолучитьБуферДвоичныхДанныхИзHexСтроки(КлючHex);
	
	opad = ПолучитьБуферДвоичныхДанныхИзHexСтроки(ПовторитьСтроку("5c", РазмерБлока));
	ipad = ПолучитьБуферДвоичныхДанныхИзHexСтроки(ПовторитьСтроку("36", РазмерБлока));

	ipad.ЗаписатьПобитовоеИсключительноеИли(0, КлючБуфер);
	ikeypad = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(ipad);
	
	opad.ЗаписатьПобитовоеИсключительноеИли(0, КлючБуфер);
	okeypad = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(opad);
	
	Возврат SHA512(СклеитьДвоичныеДанные(okeypad, ПолучитьДвоичныеДанныеИзHexСтроки(SHA512(СклеитьДвоичныеДанные(ikeypad, ДанныеДв)))));
	
КонецФункции // HMAC512(пКлюч, пДанные)

В прилагаемой обработке реализованы механизмы расчёта SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256, а также HMAC на базе этих Hash функций.

HMAC HMAC512 SHA-2 SHA-512 SHA512 8.3.11 HMAC-SHA512

См. также

Запрет глобального поиска в конфигурации

Защита ПО и шифрование Платформа 1С v8.3 1С:Бухгалтерия 3.0 Абонемент ($m)

Представляю вам микрорасширение, которое запрещает глобальный поиск по вашей конфигурации.

1 стартмани

09.02.2023    2223    9    aximo    4    

2

Как защитить pdf файл

Защита ПО и шифрование Абонемент ($m)

Для установки защиты pdf документа, полученного в 1С, написано консольное приложение на c#., использующее одну зависимость pdfSharp.dll. В результате работы приложения ограничены операции над документом и записаны метаданные. С помощью аргументов командной строки можно управлять работой приложения.

2 стартмани

30.01.2023    1657    1    olevlasam    3    

3

Универсальный синтаксический анализатор ASN.1 для декодирования .key, .cer, .der, .p7m, .p7s, .crt, .pem

Защита ПО и шифрование Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Универсальный синтаксический анализатор ASN.1, который может декодировать любую допустимую структуру ASN.1 DER или BER, независимо от того, закодирована ли она в кодировке Base64 (распознаются необработанные base64, защита PEM и begin-base64) или в шестнадцатеричном кодировании.

1 стартмани

04.12.2022    2983    12    keyn5565`    0    

13

Шифрование строки на основе мастер-пароля в 1С Предприятие 8.3.19

Защита ПО и шифрование Платформа 1С v8.3 Абонемент ($m)

Демонстрация возможностей шифрования строки на основе мастер-пароля в 1С Предприятие 8.3.19. AES без zip файла, RSA, PKDF2. (c использованием библиотеки С# через com).

2 стартмани

31.08.2022    3829    7    vit59    2    

6

Обфускатор байт-кода

Защита ПО и шифрование Платформа 1С v8.3 Конфигурации 1cv8 Россия Абонемент ($m)

Обработка, позволяющая запутывать и шифровать байт-код, поставлять модули без исходных текстов и т.д. Протестировано на платформе 8.3.23.1739.

10 стартмани

16.06.2022    10292    79    ZhokhovM    12    

40

Как уберечь конструкторскую документацию от воровства конкурентами?

Защита ПО и шифрование Платформа 1С v7.7 Платформа 1С v8.3 Абонемент ($m)

Как уберечь конструкторскую документацию от воровства конкурентами? Недавно столкнулся с этой проблемой. Заказчик серьёзно обеспокоен утечкой информации о конструкторских разработках в адрес конкурентов, за счет подкупа исполнителей, занимающихся производством по конструкторской документации, операторов технологического оборудования и обрабатывающих центров по изготовлению деталей и сборочных единиц.

2 стартмани

09.03.2022    5654    3    ge_ni    9    

2

Защита конфигураций, обработок, расширений 1С онлайн, управление версиями

Защита ПО и шифрование Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Система построена на веб платформе, все управление происходит на сайте в личном кабинете пользователя.

1 стартмани

27.12.2021    4556    2    idm80    11    

9
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. bonv 1510 29.04.20 13:26 Сейчас в теме
(0) Какие сервисы используют HMAC-SHA512?
2. nomad_irk 71 29.04.20 13:39 Сейчас в теме
(1)exmo.me при работе по API для авторизации, например
mrsmrv; bonv; +2 Ответить
3. nomad_irk 71 29.04.20 14:05 Сейчас в теме
Что есть

ПовторитьСтроку(Строка, РазмерБлока)

и

СклеитьДвоичныеДанные(ДвоичныеДанные, ДвоичныеДанные)

?
4. mrsmrv 125 29.04.20 15:37 Сейчас в теме
(3)
Функция ПовторитьСтроку(Строка, Количество)
	
	Части = Новый Массив();
	Для к = 1 По Количество Цикл
		Части.Добавить(Строка);
	КонецЦикла;
	
	Возврат СтрСоединить(Части, "");
	
КонецФункции

Функция СклеитьДвоичныеДанные(ДвоичныеДанные1, ДвоичныеДанные2)
	
	МассивДвоичныхДанных = Новый Массив;
	МассивДвоичныхДанных.Добавить(ДвоичныеДанные1);
	МассивДвоичныхДанных.Добавить(ДвоичныеДанные2);
	
	Возврат СоединитьДвоичныеДанные(МассивДвоичныхДанных);
	
КонецФункции

Показать
nomad_irk; +1 Ответить
5. mrsmrv 125 29.04.20 17:17 Сейчас в теме
(3) Добавил в публикацию, спасибо, не углядел.
6. nomad_irk 71 29.04.20 18:09 Сейчас в теме
(5)Ага. Теперь удалось протестировать.
Результат вычислений - корректный
Скорость - супер

на скрине замера производительности

верхняя строчка - JScript(с помощью COMОбъект("MSScriptControl.ScriptControl"))
нижняя - native 1С.

Тестировал на платформе 8.3.16.1063
Прикрепленные файлы:
7. mrsmrv 125 29.04.20 18:15 Сейчас в теме
(6) а я вот только что заметил что при публикации некоторые переменные "поплыли" - я их не переименовывал, взял как они были в википедии, обратил внимание что там греческие буквы, но в 1с работает. А при публикации что-то уехало
8. nomad_irk 71 29.04.20 18:17 Сейчас в теме
(7)угу, я тупо назвал t11 и t12 :)
9. vsesam80 01.05.20 18:36 Сейчас в теме
(7)А есть ли возможность реализовать шифрование строки средствами 1С языка? По сложнее чем Виженер.
10. mrsmrv 125 01.05.20 18:48 Сейчас в теме
(9) Поподробнее опишите задачу.
Расчёт Hash суммы это не шифрование, если что. Это всего лишь расчёт некоей гарантированно* уникальной последовательности символов - суммы, которая соответствует конкретной строке (с ключом).

* уникальность значит что найти исходное сообщение (или их набор) заведомо невозможно в разумное время при всех имеющихся у человечества мощностях. Или так, найти вторую последовательность данных, приводящую к такой же
Hash сумме.
11. vsesam80 01.05.20 19:12 Сейчас в теме
(10)Я понимаю что это не шифрование. Я интересуюсь можно ли сделать шифрование строки средствами языка 1С. По лучше чем Виженер к примеру. Например хранить пароли в справочнике, лицевые счета и пр. в зашифрованном виде. И еще что важно - использовать на мобильной платформе.
12. mrsmrv 125 01.05.20 20:41 Сейчас в теме
(11) Не вижу проблем реализовать. Тем более имеющимися инструментами текущей платформы. Раньше, особенно на демоверсии 8-ки в 2003-м приходилось писать свою библиотеку математических операций. А теперь, когда с двоичными данными можно побитовые операции осуществлять, то реализовать стало намного проще самые разные алгоритмы обработки данных. Другой вопрос, что если надо зашифровать например большой объём данных, то наверное всё же быстрее будет использовать спец. средства, библиотеки, ускорители и т.п.
Пароли хранить в справочнике? Можно организовать двухфакторную авторизацию.
13. mrsmrv 125 01.05.20 20:48 Сейчас в теме
(11) вот здесь например виженером проходят но ключ хеширован https://infostart.ru/public/1083158/ или вот: https://infostart.ru/public/518576/ или https://infostart.ru/public/363830/
16. mrsmrv 125 07.05.20 12:49 Сейчас в теме
14. mrsmrv 125 04.05.20 19:56 Сейчас в теме
(6) А как вам удалось получить такие цифры. У меня медленнее, процессор вроде не тормозной, причем при первом запуске быстрее:
Возврат SHA512(пДанные, лТекСтандарт.Размер); 1 0,054154 76,10
потом результаты:
Возврат SHA512(пДанные, лТекСтандарт.Размер); 1 0,085191 74,88
Странно конечно, но там и задач параллельно крутится много, скорее всего влияет занятость. Но у вас результаты на несколько порядков быстрее.
Прикрепленные файлы:
15. nomad_irk 71 04.05.20 21:12 Сейчас в теме
(14)Это я неправильно вывел результат :)
Правильный будет вот таким:
Прикрепленные файлы:
17. serg61 61 08.05.20 10:43 Сейчас в теме
18. mrsmrv 125 14.05.20 15:15 Сейчас в теме
Оптимизации. Проанализированы наиболее нагруженные строки кода, по количеству вызовов и общему времени их выполнения и проведена небольшая оптимизация, которая проявляется хорошо на довольно больших объёмах данных, например на 4 килобайтном входном массиве, для которого нужно посчитать HASH512. В скриншоте видно, какие строки и насколько ускорились. И оценить общее время затраченное на расчёты.
Были изменены следующие функции:
// функция осуществляет циклический сдвиг влево
//
Функция ЦиклическийСдвигВлево64(лМассивСтепеней2,пЧисло, пСмещение)
	Возврат ПривестиК64Битам(Цел(пЧисло/лМассивСтепеней2[64-пСмещение]) + пЧисло*лМассивСтепеней2[пСмещение]);
КонецФункции // ЦиклическийСдвигВлево64(пЧисло, пСмещение)

// функция осуществляет циклический сдвиг вправо
//
Функция ЦиклическийСдвигВправо64(лМассивСтепеней2,пЧисло, пСмещение)
	Возврат ПривестиК64Битам(Цел(пЧисло/лМассивСтепеней2[пСмещение]) + пЧисло*лМассивСтепеней2[64-пСмещение]);
КонецФункции // ЦиклическийСдвигВправо64(пЧисло, пСмещение)

Функция ПобитовыйСдвигВправо64(лМассивСтепеней2,пЧисло, пСмещение)
	Возврат Цел(пЧисло/лМассивСтепеней2[пСмещение])
КонецФункции // ПобитовыйСдвигВправо64(пЧисло, пСмещение)

Функция ПобитовыйСдвигВлево64(лМассивСтепеней2,пЧисло, пСмещение)
	ПривестиК64Битам(пЧисло*лМассивСтепеней2[пСмещение]);
КонецФункции // ПобитовыйСдвигВлево64(пЧисло, пСмещение)

Функция ПривестиК64Битам(пЧисло)
	Если пЧисло<18446744073709551616 Тогда
		Возврат пЧисло
	Иначе
		Возврат пЧисло%18446744073709551616;
	КонецЕсли;
КонецФункции // ПривестиК64Битам(пЧисло)

Функция ПолучитьМассивСтепеней2()
	лМассивСтепеней2 = Новый Массив;
	Для н=0 по 64 Цикл
		лМассивСтепеней2.Добавить(pow(2,н));
	КонецЦикла;
	Возврат лМассивСтепеней2;
КонецФункции

Функция SHA512(пДвоичныеДанные, пРазмер="512") Экспорт
	//Пояснения:
	// Все переменные беззнаковые, имеют размер 64 бита и при вычислениях суммируются по модулю 2^64
	// message — исходное двоичное сообщение
	// m — преобразованное сообщение
	
	// Инициализация переменных
	// (первые 64 бита дробных частей квадратных корней первых восьми простых чисел [от 2 до 19]):
	
	Если пРазмер = "512" Тогда
		h0 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("6a09e667f3bcc908");
		h1 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("bb67ae8584caa73b");
		h2 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("3c6ef372fe94f82b");
		h3 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("a54ff53a5f1d36f1");
		h4 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("510e527fade682d1");
		h5 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("9b05688c2b3e6c1f");
		h6 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("1f83d9abfb41bd6b");
		h7 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("5be0cd19137e2179");
	ИначеЕсли пРазмер = "384" Тогда
		h0 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("CBBB9D5DC1059ED8");
		h1 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("629A292A367CD507");
		h2 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("9159015A3070DD17");
		h3 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("152FECD8F70E5939");
		h4 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("67332667FFC00B31");
		h5 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("8EB44A8768581511");
		h6 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("DB0C2E0D64F98FA7");
		h7 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("47B5481DBEFA4FA4");
	ИначеЕсли пРазмер = "256" Тогда
		h0 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("22312194FC2BF72C");
		h1 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("9F555FA3C84C64C2");
		h2 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("2393B86B6F53B151");
		h3 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("963877195940EABD");
		h4 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("96283EE2A88EFFE3");
		h5 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("BE5E1E2553863992");
		h6 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("2B0199FC2C85B8AA");
		h7 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("0EB72DDC81C52CA2");
	ИначеЕсли пРазмер = "224" Тогда
		h0 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("8C3D37C819544DA2");
		h1 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("73E1996689DCD4D6");
		h2 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("1DFAB7AE32FF9C82");
		h3 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("679DD514582F9FCF");
		h4 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("0F6D2B697BD44DA8");
		h5 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("77E36F7304C48942");
		h6 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("3F9D85A86A1D36C8");
		h7 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("1112E6AD91D692A1");
	КонецЕсли;
	
	//Таблица констант
	//(первые 64 бита дробных частей кубических корней первых 80 простых чисел [от 2 до 409]):
	
	лМассивСтепеней2 = ПолучитьМассивСтепеней2();
	
	лСтрока = "
	|428a2f98d728ae22,7137449123ef65cd,b5c0fbcfec4d3b2f,e9b5dba58189dbbc,
	|3956c25bf348b538,59f111f1b605d019,923f82a4af194f9b,ab1c5ed5da6d8118,
	|d807aa98a3030242,12835b0145706fbe,243185be4ee4b28c,550c7dc3d5ffb4e2,
	|72be5d74f27b896f,80deb1fe3b1696b1,9bdc06a725c71235,c19bf174cf692694,
	|e49b69c19ef14ad2,efbe4786384f25e3,0fc19dc68b8cd5b5,240ca1cc77ac9c65,
	|2de92c6f592b0275,4a7484aa6ea6e483,5cb0a9dcbd41fbd4,76f988da831153b5,
	|983e5152ee66dfab,a831c66d2db43210,b00327c898fb213f,bf597fc7beef0ee4,
	|c6e00bf33da88fc2,d5a79147930aa725,06ca6351e003826f,142929670a0e6e70,
	|27b70a8546d22ffc,2e1b21385c26c926,4d2c6dfc5ac42aed,53380d139d95b3df,
	|650a73548baf63de,766a0abb3c77b2a8,81c2c92e47edaee6,92722c851482353b,
	|a2bfe8a14cf10364,a81a664bbc423001,c24b8b70d0f89791,c76c51a30654be30,
	|d192e819d6ef5218,d69906245565a910,f40e35855771202a,106aa07032bbd1b8,
	|19a4c116b8d2d0c8,1e376c085141ab53,2748774cdf8eeb99,34b0bcb5e19b48a8,
	|391c0cb3c5c95a63,4ed8aa4ae3418acb,5b9cca4f7763e373,682e6ff3d6b2b8a3,
	|748f82ee5defb2fc,78a5636f43172f60,84c87814a1f0ab72,8cc702081a6439ec,
	|90befffa23631e28,a4506cebde82bde9,bef9a3f7b2c67915,c67178f2e372532b,
	|ca273eceea26619c,d186b8c721c0c207,eada7dd6cde0eb1e,f57d4f7fee6ed178,
	|06f067aa72176fba,0a637dc5a2c898a6,113f9804bef90dae,1b710b35131c471b,
	|28db77f523047d84,32caab7b40c72493,3c9ebe0a15c9bebc,431d67c49c100d4c,
	|4cc5d4becb3e42b6,597f299cfc657e2a,5fcb6fab3ad6faec,6c44198c4a475817";
	Конст = ПолучитьМассивБДДИзHexСтроки(лСтрока);
	
	//Предварительная обработка:
	//m := m ǁ [k нулевых бит], где k — наименьшее неотрицательное число, такое что 
	//                 (L + 1 + K) mod 1024 = 960, где L — число бит в сообщении (сравнима по модулю 1024 c 960)
	//m := m ǁ Длина(message) — длина исходного сообщения в битах в виде 64-битного числа
	//            с порядком байтов от старшего к младшему
	
	msg = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(пДвоичныеДанные);
	L = msg.Размер*8; // получаем размер в битах
	K1 = 1024 - ((L + 64 + 1) % 1024); // сколько бит нужно добавить
	K = K1 - 7; // Потому что засчитали один бит, а добавлять будем целый байт с лидирующим битом
	КолвоHEX = K/8; // считаем количество добавляемых байтов
	лБуферДвДанных = Новый БуферДвоичныхДанных(КолвоHEX,ПорядокБайтов.BigEndian);
	лМассивБухДвДанных = Новый Массив();
	лМассивБухДвДанных.Добавить(msg);
	лМассивБухДвДанных.Добавить(ПолучитьБуферДвоичныхДанныхИзHexСтроки("80"));
	лМассивБухДвДанных.Добавить(лБуферДвДанных);
	
	лБуферДвДанных2 = Новый БуферДвоичныхДанных(8,ПорядокБайтов.BigEndian);
	
	лБуферДвДанных2.ЗаписатьЦелое64(0,L,ПорядокБайтов.BigEndian);
	лМассивБухДвДанных.Добавить(лБуферДвДанных2);
	
	msg = СоединитьБуферыДвоичныхДанных(лМассивБухДвДанных,,ПорядокБайтов.BigEndian);
	
	//разбить сообщение на куски по 512 бит
	лМассив = РазделитьДвоичныеДанные(ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(msg),128);
	
	h_0 = h0.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_1 = h1.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_2 = h2.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_3 = h3.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_4 = h4.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_5 = h5.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_6 = h6.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	h_7 = h7.ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
	
	//Далее сообщение обрабатывается последовательными порциями по 1024 бит:
	Для Каждого лКусок1 Из лМассив Цикл
		//    разбить кусок на 16 слов длиной 64 бита (с порядком байтов от старшего к младшему внутри слова): w[0..15]
		лМассив2 = РазделитьДвоичныеДанные(лКусок1,8);
		Для i=16 по 79 Цикл
			лЦел15 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(лМассив2[i-15]).ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
			лЦел2 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(лМассив2[i-2]).ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian);
			//    Сгенерировать дополнительные 48 слов:
			//    для i от 16 до 63
			//        s0 := (w[i-15] rotr 7) xor (w[i-15] rotr 18) xor (w[i-15] shr 3)
			//        s1 := (w[i-2] rotr 17) xor (w[i-2] rotr 19) xor (w[i-2] shr 10)
			//        w[i] := w[i-16] + s0 + w[i-7] + s1
			s0 = ПобитовоеИсключительноеИли64(ПобитовоеИсключительноеИли64(ЦиклическийСдвигВправо64(лМассивСтепеней2,лЦел15,1),ЦиклическийСдвигВправо64(лМассивСтепеней2,лЦел15,8)),Цел(лЦел15/128));
			s1 = ПобитовоеИсключительноеИли64(ПобитовоеИсключительноеИли64(ЦиклическийСдвигВправо64(лМассивСтепеней2,лЦел2,19),ЦиклическийСдвигВправо64(лМассивСтепеней2,лЦел2,61)),Цел(лЦел2/64));
			лБуфер64 = Новый БуферДвоичныхДанных(8,ПорядокБайтов.BigEndian);
			лЦел64 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(лМассив2[i-16]).ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian) + s0 + ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(лМассив2[i-7]).ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian) + s1;
			лЦел64 = ПривестиК64Битам(лЦел64);
			лБуфер64.ЗаписатьЦелое64(0,лЦел64,ПорядокБайтов.BigEndian);
			лМассив2.Добавить(ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(лБуфер64));
		КонецЦикла;
		
		//    Инициализация вспомогательных переменных:
		a = h_0;
		b = h_1;
		c = h_2;
		d = h_3;
		e = h_4;
		f = h_5;
		g = h_6;
		h = h_7;
		//    Основной цикл:
		Для i = 0 по 79 Цикл
			S0 = ПривестиК64Битам(ПобитовоеИсключительноеИли64(ПобитовоеИсключительноеИли64(ЦиклическийСдвигВправо64(лМассивСтепеней2,a, 28), ЦиклическийСдвигВправо64(лМассивСтепеней2,a, 34)), ЦиклическийСдвигВправо64(лМассивСтепеней2,a, 39)));
			Ma = ПривестиК64Битам(ПобитовоеИсключительноеИли64(ПобитовоеИсключительноеИли64(ПобитовоеИ64(a, b), ПобитовоеИ64(a, c)), ПобитовоеИ64(b, c)));
			t2 = ПривестиК64Битам(S0 + Ma);
			S1 = ПривестиК64Битам(ПобитовоеИсключительноеИли64(ПобитовоеИсключительноеИли64(ЦиклическийСдвигВправо64(лМассивСтепеней2,e, 14), ЦиклическийСдвигВправо64(лМассивСтепеней2,e, 18)), ЦиклическийСдвигВправо64(лМассивСтепеней2,e, 41)));
			Ch = ПривестиК64Битам(ПобитовоеИсключительноеИли64(ПобитовоеИ64(e, f), ПобитовоеИ64(ПобитовоеНе64(e), g)));
			t1 = ПривестиК64Битам(h + S1 + Ch + Конст[i].ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian) + ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(лМассив2[i]).ПрочитатьЦелое64(0,ПорядокБайтов.BigEndian));
			h = g;
			g = f;
			f = e;
			e = ПривестиК64Битам(d + t1);
			d = c;
			c = b;
			b = a;
			a = ПривестиК64Битам(t1 + t2);
		КонецЦикла;
		
		//    Добавить полученные значения к ранее вычисленному результату:
		h_0 = ПривестиК64Битам(h_0 + a);
		h_1 = ПривестиК64Битам(h_1 + b);
		h_2 = ПривестиК64Битам(h_2 + c);
		h_3 = ПривестиК64Битам(h_3 + d);
		h_4 = ПривестиК64Битам(h_4 + e);
		h_5 = ПривестиК64Битам(h_5 + f);
		h_6 = ПривестиК64Битам(h_6 + g);
		h_7 = ПривестиК64Битам(h_7 + h);
		
	КонецЦикла;
	
	h0.ЗаписатьЦелое64(0,h_0,ПорядокБайтов.BigEndian);
	h1.ЗаписатьЦелое64(0,h_1,ПорядокБайтов.BigEndian);
	h2.ЗаписатьЦелое64(0,h_2,ПорядокБайтов.BigEndian);
	h3.ЗаписатьЦелое64(0,h_3,ПорядокБайтов.BigEndian);
	h4.ЗаписатьЦелое64(0,h_4,ПорядокБайтов.BigEndian);
	h5.ЗаписатьЦелое64(0,h_5,ПорядокБайтов.BigEndian);
	h6.ЗаписатьЦелое64(0,h_6,ПорядокБайтов.BigEndian);
	h7.ЗаписатьЦелое64(0,h_7,ПорядокБайтов.BigEndian);
	
	//Получить итоговое значение хеша:
	//digest = hash = h0 ǁ h1 ǁ h2 ǁ h3 ǁ h4 ǁ h5 ǁ h6 ǁ h7
	лМассив3 = Новый Массив();
	лМассив3.Добавить(h0);
	лМассив3.Добавить(h1);
	лМассив3.Добавить(h2);
	// Поскольку итоговый результат берётся не весь, то добавляем в массив нужное количество слов в зависимости от размера вывода.
	Если пРазмер = "224" Тогда
		// "распилить пополам" и взять "старшую" часть т.к. нужно взять 3.5 QWORD (64-х разрядных слова).
		лМассив3.Добавить(ПолучитьБуферДвоичныхДанныхИзHexСтроки(Лев(ПолучитьHexСтрокуИзБуфераДвоичныхДанных(h3),8)));
	Иначе
		лМассив3.Добавить(h3);
	КонецЕсли;
	Если пРазмер = "384" ИЛИ пРазмер = "512" Тогда
		лМассив3.Добавить(h4);
		лМассив3.Добавить(h5);
	КонецЕсли;
	Если пРазмер = "512" Тогда
		лМассив3.Добавить(h6);
		лМассив3.Добавить(h7);
	КонецЕсли;
	Буфер3 = СоединитьБуферыДвоичныхДанных(лМассив3);
	
	digest = Нрег(ПолучитьHexСтрокуИзБуфераДвоичныхДанных(Буфер3));
	
	Возврат digest;
	
КонецФункции // SHA512(пДвоичныеДанные, пРазмер="512") Экспорт
	

Показать
Прикрепленные файлы:
19. nomad_irk 71 14.05.20 15:37 Сейчас в теме
(18) на маленьких объемах шифруемых данных тоже наблюдается ускорение - 0.07 секунды разницы. Было 0.3208, стало - 0.2547
Прикрепленные файлы:
sant78; mrsmrv; +2 Ответить
20. Aletar 25.07.20 20:52 Сейчас в теме
В 8.3.18 добавили SHA-512
a.babenko; +1 Ответить
21. mrsmrv 125 26.07.20 07:20 Сейчас в теме
(20) Это очень хорошо, но "промежуточные" стандарты SHA-224, SHA-384, SHA-512/224, SHA-512/256 не заявлены в платформе 1с, так что обработка остаётся актуальной.

Дело в том, что для "урезанных" вариантов sha-512 не просто обрезается выходная часть хеша, а применяются другие наборы констант. Впрочем, для sha-224 тоже. И в прилагаемой обработке всё это реализовано. Думаю, она ещё послужит :-)

для sha-224:
	Если пРазмер="256" Тогда
		h0 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("6A09E667");
		h1 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("BB67AE85");
		h2 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("3C6EF372");
		h3 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("A54FF53A");
		h4 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("510E527F");
		h5 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("9B05688C");
		h6 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("1F83D9AB");
		h7 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("5BE0CD19");
	ИначеЕсли пРазмер="224" Тогда
		h0 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("c1059ed8");
		h1 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("367cd507");
		h2 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("3070dd17");
		h3 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("f70e5939");
		h4 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("ffc00b31");
		h5 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("68581511");
		h6 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("64f98fa7");
		h7 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("befa4fa4");
	КонецЕсли;
Показать

для SHA-384, SHA-512/224, SHA-512/256:
	Если пРазмер = "512" Тогда
		h0 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("6a09e667f3bcc908");
		h1 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("bb67ae8584caa73b");
		h2 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("3c6ef372fe94f82b");
		h3 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("a54ff53a5f1d36f1");
		h4 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("510e527fade682d1");
		h5 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("9b05688c2b3e6c1f");
		h6 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("1f83d9abfb41bd6b");
		h7 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("5be0cd19137e2179");
	ИначеЕсли пРазмер = "384" Тогда
		h0 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("CBBB9D5DC1059ED8");
		h1 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("629A292A367CD507");
		h2 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("9159015A3070DD17");
		h3 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("152FECD8F70E5939");
		h4 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("67332667FFC00B31");
		h5 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("8EB44A8768581511");
		h6 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("DB0C2E0D64F98FA7");
		h7 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("47B5481DBEFA4FA4");
	ИначеЕсли пРазмер = "256" Тогда
		h0 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("22312194FC2BF72C");
		h1 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("9F555FA3C84C64C2");
		h2 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("2393B86B6F53B151");
		h3 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("963877195940EABD");
		h4 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("96283EE2A88EFFE3");
		h5 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("BE5E1E2553863992");
		h6 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("2B0199FC2C85B8AA");
		h7 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("0EB72DDC81C52CA2");
	ИначеЕсли пРазмер = "224" Тогда
		h0 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("8C3D37C819544DA2");
		h1 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("73E1996689DCD4D6");
		h2 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("1DFAB7AE32FF9C82");
		h3 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("679DD514582F9FCF");
		h4 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("0F6D2B697BD44DA8");
		h5 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("77E36F7304C48942");
		h6 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("3F9D85A86A1D36C8");
		h7 = ПолучитьБуферДвоичныхДанныхИзHexСтроки("1112E6AD91D692A1");
	КонецЕсли;
Показать
22. nailmail 06.04.22 11:08 Сейчас в теме
Ваша обработка оказалась для меня очень ценной, большое спасибо!

Но однажды что-то пошло не так:

строка, передаваемая HMAC512:
TESTTEST2АМ-00007633dO4pgeu8GZVQHt5HBAqnfVVYhCWXcl4Uz0Tx1649230268/api-private/catalog/item12Test12PRODUCT796шт20

ключ, передаваемый HMAC512:
RkmoPkX0iF57gvyhV4qIxBbZqE6wSr1NFN6x

результат HMAC512:
2a12cbac17b10ed7d20c2233a77ed3fc5c40a683e67072a993885e11b5aa­d7434a3e87ec35133d1c23b58563e7d520ee9261243a51611f228911be62­c949b115

-------
корректный результат (https://www.freeformatter.com/hmac-generator.html#ad-output):
bb78ea6a3828bde380e18ce734165ad798fadb86534c30ec726053a4cc2b­d15ef52e164bbde7c9780fd1987ce2af2367dd0bf1cdf5146b6ac0066fc2­07d99639

Я только обнаружил проблему и еще не пытался выяснить причину, возможно, у вас уже имеется исправленное решение?
jo0506; mrsmrv; +2 Ответить
23. nailmail 06.04.22 11:27 Сейчас в теме
(22)
Первое, что заметил - если содержимое строки увеличить на 4 или более знаков, то всё ок

На всякий случай обновил оптимизированные функции из сообщения 18 - не помогло.
24. mrsmrv 125 09.04.22 16:44 Сейчас в теме
(23)
Оказалось, что при длине входных данных более 111 байт, и менее 119 байт нужно увеличивать входное сообщение на целый блок.
В общем поправил алгоритм, заодно немного его упростив.

В приведённом в комментарии (18) имплементации Нужно заменить кусок кода:
    msg = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(пДвоичныеДанные);
    L = msg.Размер*8; // получаем размер в битах
    K1 = 1024 - ((L + 64 + 1) % 1024); // сколько бит нужно добавить
    K = K1 - 7; // Потому что засчитали один бит, а добавлять будем целый байт с лидирующим битом
    КолвоHEX = K/8; // считаем количество добавляемых байтов

На

    msg = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(пДвоичныеДанные);
    L = msg.Размер*8; // получаем размер в битах
	лРазмер = msg.Размер%128;
    K1 = 112 - лРазмер;
	Если лРазмер > 111 Тогда
		K1 = K1 + 128;
	КонецЕсли;
    КолвоHEX = K1 + 7; // Потому что засчитали один бит, а добавлять будем целый байт с лидирующим битом

Показать


Приложил исправленную обработку.
Прикрепленные файлы:
ПроверкаХешФункций3.epf
nailmail; +1 Ответить
25. mrsmrv 125 10.04.22 13:08 Сейчас в теме
(23)
Можно заменить строчку расчёта K1:

K1 = 1024 - ((L + 128 + 1) % 1024) + 64; // сколько бит нужно добавить


ну или сразу: КолвоHEX = (1081 - ((L + 129) % 1024))/8
nailmail; +1 Ответить
26. efin 14.12.22 20:24 Сейчас в теме
Возможно ли подобным способом реализовать bcrypt? А на заказ?
27. jo0506 19 24.01.23 09:48 Сейчас в теме
Почему на php
hash_hmac('sha512', $preSign, $apisecret) 

результат один, а на 1с:
HMAC512(СекретныйКлюч, preSign)

Что не так??? Либо это не аналог функции php - hash_hmac???
28. jo0506 19 24.01.23 12:08 Сейчас в теме
(27) Блин 2 дня убил, оказывается, надо было Функцию SHA2(пДанные, пСтандарт="SHA-512") результат в нижний регистр было сделать:
Код
Возврат НРЕГ(ПолучитьHexСтрокуИзБуфераДвоичныхДанных(SHA512(лДанныеБуфер, лТекСтандарт.Размер)));
Показать полностью
Оставьте свое сообщение