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

Публикация № 1230060 29.04.20

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

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

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

Во встроенном языке текущей версии, на момент публикации нет штатных средств для расчета Хеша по алгоритму 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 функций.

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

Наименование Файл Версия Размер
SHA512 и HMAC512 на 1С 8 без использования внешних компонент:

.epf 17,98Kb
88
.epf 1.0 17,98Kb 88 Скачать бесплатно

Специальные предложения

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

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

и

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

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

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

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

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

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

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

* уникальность значит что найти исходное сообщение (или их набор) заведомо невозможно в разумное время при всех имеющихся у человечества мощностях. Или так, найти вторую последовательность данных, приводящую к такой же
Hash сумме.
11. vsesam80 01.05.20 19:12 Сейчас в теме
(10)Я понимаю что это не шифрование. Я интересуюсь можно ли сделать шифрование строки средствами языка 1С. По лучше чем Виженер к примеру. Например хранить пароли в справочнике, лицевые счета и пр. в зашифрованном виде. И еще что важно - использовать на мобильной платформе.
12. mrsmrv 107 01.05.20 20:41 Сейчас в теме
(11) Не вижу проблем реализовать. Тем более имеющимися инструментами текущей платформы. Раньше, особенно на демоверсии 8-ки в 2003-м приходилось писать свою библиотеку математических операций. А теперь, когда с двоичными данными можно побитовые операции осуществлять, то реализовать стало намного проще самые разные алгоритмы обработки данных. Другой вопрос, что если надо зашифровать например большой объём данных, то наверное всё же быстрее будет использовать спец. средства, библиотеки, ускорители и т.п.
Пароли хранить в справочнике? Можно организовать двухфакторную авторизацию.
13. mrsmrv 107 01.05.20 20:48 Сейчас в теме
(11) вот здесь например виженером проходят но ключ хеширован https://infostart.ru/public/1083158/ или вот: https://infostart.ru/public/518576/ или https://infostart.ru/public/363830/
16. mrsmrv 107 07.05.20 12:49 Сейчас в теме
14. mrsmrv 107 04.05.20 19:56 Сейчас в теме
(6) А как вам удалось получить такие цифры. У меня медленнее, процессор вроде не тормозной, причем при первом запуске быстрее:
Возврат SHA512(пДанные, лТекСтандарт.Размер); 1 0,054154 76,10
потом результаты:
Возврат SHA512(пДанные, лТекСтандарт.Размер); 1 0,085191 74,88
Странно конечно, но там и задач параллельно крутится много, скорее всего влияет занятость. Но у вас результаты на несколько порядков быстрее.
Прикрепленные файлы:
15. nomad_irk 63 04.05.20 21:12 Сейчас в теме
(14)Это я неправильно вывел результат :)
Правильный будет вот таким:
Прикрепленные файлы:
17. serg61 56 08.05.20 10:43 Сейчас в теме
18. mrsmrv 107 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 63 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 107 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 107 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 107 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 15 24.01.23 09:48 Сейчас в теме
Почему на php
hash_hmac('sha512', $preSign, $apisecret) 

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

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

См. также

От Hello world - к защите конфигураций за 1 минуту Промо

Защита ПО и шифрование Математика и алгоритмы Платформа 1С v8.3 Платформа 1С v8.3 Конфигурации 1cv8 Конфигурации 1cv8 Бесплатно (free) Бесплатно (free)

Вы всегда хотели но боялись создать COM объект? Тогда мы идем к вам! С обычным блокнотом, где будем программировать на c#, и таймером ...

19.05.2012    36355    O-Planet    130    

Информационная безопасность 1С: Памятка для Обновлятора 1С

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

— Три магнитофона, три кинокамеры заграничных, три портсигара отечественных, куртка замшевая... три...

10.12.2020    5095    Indgo    63    

Расшифровка DataMatrix кода с пачки сигарет (табачная продукция)

Защита ПО и шифрование Платформа 1С v8.3 Платформа 1С v8.3 Россия Россия Бесплатно (free) Бесплатно (free)

Разбор считанного DataMatrix кода с пачки сигарет - какие символы за что отвечают. Декодирование МРЦ

07.06.2020    14790    Tasselhof    10    

Кодирование по алфавиту. Большие целые числа

Защита ПО и шифрование Платформа 1С v8.3 Платформа 1С v8.3 Конфигурации 1cv8 Конфигурации 1cv8 Бесплатно (free) Бесплатно (free)

А вы знали, что 1С умеет в очень длинные числа? Кодирование информации в строку по указанному алфавиту, возможен любой алфавит и не только. В тексте приведён алгоритм для кодирования последовательности байт в любой и из любого односимвольного алфавита.

14.05.2020    3063    mrsmrv    5    

Танцы с бубном! Создаём демонстрационную базу

Защита ПО и шифрование Платформа 1С v8.3 Платформа 1С v8.3 Бесплатно (free) Бесплатно (free)

В статье кратко расскажу Вам о моём опыте создания демонстрационной версии базы данных 1С и способах защиты кода.

08.02.2018    17603    user748289    41    

Симметричное шифрование в 1С

Защита ПО и шифрование Платформа 1С v8.3 Платформа 1С v8.3 Конфигурации 1cv8 Конфигурации 1cv8 Бесплатно (free) Бесплатно (free)

Настоящая статья посвящена реализации в 1С симметричного шифрования встроенными механизмами

02.06.2015    29968    alex271    8    

Защита конфигурации от ...

Защита ПО и шифрование Платформа 1С v8.3 Платформа 1С v8.3 Управляемые формы Управляемые формы Конфигурации 1cv8 Конфигурации 1cv8 Бесплатно (free) Бесплатно (free)

Бывают моменты в жизни, когда нужно сделать возможность входа только одному пользователю после определенного времени. Ниже приведен такой код.

18.05.2015    19548    hakerxp    28    

И ещё несколько слов о защите разработок...

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

Дневные мысли о механизмах защиты кода... (по мотивам http://www.infostart.ru/profile/8914/blogs/660/)

30.10.2008    42305    ValeriVP    81    

Простые примеры реализации демо-версий обработок на платформе «1С:Предприятие 8».

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

Каждый из тех кто продает свой интеллектуальный труд, не раз сталкивался с необходимостью создания демо-версии разработки, дабы продемонстрировать клиенту функциональность, но при этом сохранить для клиента потребность в приобретении полнофункциональной версии. В этой статье я хотел бы рассмотреть несколько не сложных примеров создания демо-версий обработок/отчетов для платформы «1С:Предприятие 8».

06.05.2008    25044    coder1cv8    40